PageRenderTime 49ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/sys/emu/MacOSX/os.c

https://gitlab.com/mcepl/acme-sac
C | 647 lines | 478 code | 108 blank | 61 comment | 63 complexity | 93268c089b35a244cbe76ff1224331db MD5 | raw file
Possible License(s): LGPL-2.0
  1. /*
  2. * Loosely based on FreeBSD/os.c and Solaris/os.c
  3. * Copyright © 1998, 1999 Lucent Technologies Inc. All rights reserved.
  4. * Revisions Copyright © 1999, 2000 Vita Nuova Limited. All rights reserved.
  5. * Revisions Copyright © 2002, 2003 Corpus Callosum Corporation. All rights reserved.
  6. */
  7. #include "dat.h"
  8. #include "fns.h"
  9. #include "error.h"
  10. #undef _POSIX_C_SOURCE
  11. #undef getwd
  12. #include <unistd.h>
  13. #include <pthread.h>
  14. #include <time.h>
  15. #include <termios.h>
  16. #include <signal.h>
  17. #include <pwd.h>
  18. #include <sys/resource.h>
  19. #include <sys/time.h>
  20. #include <sys/socket.h>
  21. #include <sched.h>
  22. #include <errno.h>
  23. #include <sys/ucontext.h>
  24. #include <sys/types.h>
  25. #include <sys/stat.h>
  26. #include <mach/mach_init.h>
  27. #include <mach/task.h>
  28. #include <mach/vm_map.h>
  29. #if defined(__ppc__)
  30. #include <architecture/ppc/cframe.h>
  31. #endif
  32. enum
  33. {
  34. DELETE = 0x7F
  35. };
  36. char *hosttype = "MacOSX";
  37. char *cputype = "power";
  38. static pthread_key_t prdakey;
  39. extern int dflag;
  40. Proc *
  41. getup(void) {
  42. return (Proc *)pthread_getspecific(prdakey);
  43. }
  44. /* Pthread version */
  45. void
  46. pexit(char *msg, int t)
  47. {
  48. Osenv *e;
  49. Proc *p;
  50. USED(t);
  51. USED(msg);
  52. lock(&procs.l);
  53. p = up;
  54. if(p->prev)
  55. p->prev->next = p->next;
  56. else
  57. procs.head = p->next;
  58. if(p->next)
  59. p->next->prev = p->prev;
  60. else
  61. procs.tail = p->prev;
  62. unlock(&procs.l);
  63. if(0)
  64. print("pexit: %s: %s\n", p->text, msg);
  65. e = p->env;
  66. if(e != nil) {
  67. closefgrp(e->fgrp);
  68. closepgrp(e->pgrp);
  69. closeegrp(e->egrp);
  70. closesigs(e->sigs);
  71. }
  72. free(e->user);
  73. free(p->prog);
  74. free(p);
  75. pthread_exit(0);
  76. }
  77. void
  78. trapBUS(int signo)
  79. {
  80. USED(signo);
  81. disfault(nil, "Bus error");
  82. }
  83. void
  84. trapUSR1(int signo)
  85. {
  86. USED(signo);
  87. if(up->type != Interp) /* Used to unblock pending I/O */
  88. return;
  89. if(up->intwait == 0) /* Not posted so its a sync error */
  90. disfault(nil, Eintr); /* Should never happen */
  91. up->intwait = 0; /* Clear it so the proc can continue */
  92. }
  93. void
  94. trapILL(int signo)
  95. {
  96. USED(signo);
  97. disfault(nil, "Illegal instruction");
  98. }
  99. /* from geoff collyer's port */
  100. void
  101. printILL(int sig, siginfo_t *siginfo, void *v)
  102. {
  103. USED(sig);
  104. USED(v);
  105. panic("Illegal instruction with code=%d at address=%x, opcode=%x.\n"
  106. ,siginfo->si_code, siginfo->si_addr,*(char*)siginfo->si_addr);
  107. }
  108. void
  109. trapSEGV(int signo)
  110. {
  111. USED(signo);
  112. disfault(nil, "Segmentation violation");
  113. }
  114. void
  115. trapFPE(int signo)
  116. {
  117. USED(signo);
  118. disfault(nil, "Floating point exception");
  119. }
  120. static void
  121. setsigs(void)
  122. {
  123. struct sigaction act;
  124. memset(&act, 0 , sizeof(act));
  125. /*
  126. * For the correct functioning of devcmd in the
  127. * face of exiting slaves
  128. */
  129. signal(SIGPIPE, SIG_IGN);
  130. if(signal(SIGTERM, SIG_IGN) != SIG_IGN)
  131. signal(SIGTERM, cleanexit);
  132. act.sa_handler=trapUSR1;
  133. sigaction(SIGUSR1, &act, nil);
  134. if(sflag == 0) {
  135. act.sa_handler = trapBUS;
  136. sigaction(SIGBUS, &act, nil);
  137. act.sa_handler = trapILL;
  138. sigaction(SIGILL, &act, nil);
  139. act.sa_handler = trapSEGV;
  140. sigaction(SIGSEGV, &act, nil);
  141. act.sa_handler = trapFPE;
  142. sigaction(SIGFPE, &act, nil);
  143. if(signal(SIGINT, SIG_IGN) != SIG_IGN)
  144. signal(SIGINT, cleanexit);
  145. } else {
  146. act.sa_sigaction = printILL;
  147. act.sa_flags=SA_SIGINFO;
  148. sigaction(SIGILL, &act, nil);
  149. }
  150. }
  151. void *
  152. tramp(void *arg)
  153. {
  154. Proc *p = arg;
  155. p->sigid = (int)pthread_self();
  156. if(pthread_setspecific(prdakey, arg)) {
  157. print("set specific data failed in tramp\n");
  158. pthread_exit(0);
  159. }
  160. p->func(p->arg);
  161. pexit("{Tramp}", 0);
  162. return NULL;
  163. }
  164. int
  165. kproc(char *name, void (*func)(void*), void *arg, int flags)
  166. {
  167. pthread_t thread;
  168. Proc *p;
  169. Pgrp *pg;
  170. Fgrp *fg;
  171. Egrp *eg;
  172. pthread_attr_t attr;
  173. p = newproc();
  174. if(p == nil)
  175. panic("kproc: no memory");
  176. if(flags & KPDUPPG) {
  177. pg = up->env->pgrp;
  178. incref(&pg->r);
  179. p->env->pgrp = pg;
  180. }
  181. if(flags & KPDUPFDG) {
  182. fg = up->env->fgrp;
  183. incref(&fg->r);
  184. p->env->fgrp = fg;
  185. }
  186. if(flags & KPDUPENVG) {
  187. eg = up->env->egrp;
  188. incref(&eg->r);
  189. p->env->egrp = eg;
  190. }
  191. p->env->uid = up->env->uid;
  192. p->env->gid = up->env->gid;
  193. kstrdup(&p->env->user, up->env->user);
  194. strcpy(p->text, name);
  195. p->func = func;
  196. p->arg = arg;
  197. lock(&procs.l);
  198. if(procs.tail != nil) {
  199. p->prev = procs.tail;
  200. procs.tail->next = p;
  201. } else {
  202. procs.head = p;
  203. p->prev = nil;
  204. }
  205. procs.tail = p;
  206. unlock(&procs.l);
  207. up->kid = p;
  208. if((pthread_attr_init(&attr))== -1)
  209. panic("pthread_attr_init failed");
  210. errno=0;
  211. pthread_attr_setschedpolicy(&attr,SCHED_OTHER);
  212. if(errno)
  213. panic("pthread_attr_setschedpolicy failed");
  214. pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
  215. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  216. if(pthread_create(&thread, &attr, tramp, p))
  217. panic("thr_create failed\n");
  218. pthread_attr_destroy(&attr);
  219. return (int)thread;
  220. }
  221. int
  222. segflush(void *va, ulong len)
  223. {
  224. kern_return_t err;
  225. vm_machine_attribute_val_t value = MATTR_VAL_ICACHE_FLUSH;
  226. err = vm_machine_attribute( (vm_map_t)mach_task_self(),
  227. (vm_address_t)va,
  228. (vm_size_t)len,
  229. MATTR_CACHE,
  230. &value);
  231. if (err != KERN_SUCCESS) {
  232. print("segflush: failure (%d) address %lud\n", err, va);
  233. }
  234. return (int)err;
  235. }
  236. /* from geoff collyer's port
  237. invalidate instruction cache and write back data cache from a to a+n-1,
  238. at least.
  239. void
  240. segflush(void *a, ulong n)
  241. {
  242. ulong *p;
  243. // paranoia, flush the world
  244. __asm__("isync\n\t"
  245. "eieio\n\t"
  246. : // no output
  247. :
  248. );
  249. // cache blocks are often eight words (32 bytes) long, sometimes 16 bytes.
  250. // need to determine it dynamically?
  251. for (p = (ulong *)((ulong)a & ~3UL); (char *)p < (char *)a + n; p++)
  252. __asm__("dcbst 0,%0\n\t" // not dcbf, which writes back, then invalidates
  253. "icbi 0,%0\n\t"
  254. : // no output
  255. : "ar" (p)
  256. );
  257. __asm__("isync\n\t"
  258. "eieio\n\t"
  259. : // no output
  260. :
  261. );
  262. }
  263. */
  264. void
  265. oshostintr(Proc *p)
  266. {
  267. pthread_kill((pthread_t)p->sigid, SIGUSR1);
  268. }
  269. static ulong erendezvous(void*, ulong);
  270. void
  271. osblock(void)
  272. {
  273. erendezvous(up, 0);
  274. }
  275. void
  276. osready(Proc *p)
  277. {
  278. erendezvous(p, 0);
  279. }
  280. void
  281. oslongjmp(void *regs, osjmpbuf env, int val)
  282. {
  283. USED(regs);
  284. siglongjmp(env, val);
  285. }
  286. struct termios tinit;
  287. static void
  288. termset(void)
  289. {
  290. struct termios t;
  291. tcgetattr(0, &t);
  292. tinit = t;
  293. t.c_lflag &= ~(ICANON|ECHO|ISIG);
  294. t.c_cc[VMIN] = 1;
  295. t.c_cc[VTIME] = 0;
  296. tcsetattr(0, TCSANOW, &t);
  297. }
  298. static void
  299. termrestore(void)
  300. {
  301. tcsetattr(0, TCSANOW, &tinit);
  302. }
  303. void
  304. cleanexit(int x)
  305. {
  306. USED(x);
  307. if(up->intwait) {
  308. up->intwait = 0;
  309. return;
  310. }
  311. if(dflag == 0)
  312. termrestore();
  313. exit(0);
  314. }
  315. void
  316. osreboot(char *file, char **argv)
  317. {
  318. if(dflag == 0)
  319. termrestore();
  320. execvp(file, argv);
  321. panic("reboot failure");
  322. }
  323. int gidnobody= -1, uidnobody= -1;
  324. void
  325. getnobody()
  326. {
  327. struct passwd *pwd;
  328. if((pwd = getpwnam("nobody"))) {
  329. uidnobody = pwd->pw_uid;
  330. gidnobody = pwd->pw_gid;
  331. }
  332. }
  333. /* Pthread version */
  334. static pthread_mutex_t rendezvouslock;
  335. static pthread_mutexattr_t *pthread_mutexattr_default = NULL;
  336. void
  337. libinit(char *imod)
  338. {
  339. struct passwd *pw;
  340. Proc *p;
  341. char sys[64];
  342. setsid();
  343. // setup personality
  344. gethostname(sys, sizeof(sys));
  345. kstrdup(&ossysname, sys);
  346. getnobody();
  347. if(dflag == 0)
  348. termset();
  349. setsigs();
  350. if(pthread_mutex_init(&rendezvouslock, pthread_mutexattr_default))
  351. panic("pthread_mutex_init");
  352. if(pthread_key_create(&prdakey,NULL))
  353. print("key_create failed\n");
  354. p = newproc();
  355. if(pthread_setspecific(prdakey, p))
  356. panic("set specific thread data failed\n");
  357. pw = getpwuid(getuid());
  358. if(pw != nil)
  359. kstrdup(&eve, pw->pw_name);
  360. else
  361. print("cannot getpwuid\n");
  362. up->env->uid = getuid();
  363. up->env->gid = getgid();
  364. emuinit(imod);
  365. }
  366. int
  367. readkbd(void)
  368. {
  369. int n;
  370. char buf[1];
  371. n = read(0, buf, sizeof(buf));
  372. if(n < 0)
  373. print("keyboard close (n=%d, %s)\n", n, strerror(errno));
  374. if(n <= 0)
  375. pexit("keyboard thread", 0);
  376. switch(buf[0]) {
  377. case '\r':
  378. buf[0] = '\n';
  379. break;
  380. case DELETE:
  381. cleanexit(0);
  382. break;
  383. }
  384. return buf[0];
  385. }
  386. enum
  387. {
  388. NHLOG = 7,
  389. NHASH = (1<<NHLOG)
  390. };
  391. typedef struct Tag Tag;
  392. struct Tag
  393. {
  394. void* tag;
  395. ulong val;
  396. pthread_cond_t cv;
  397. Tag* next;
  398. };
  399. static Tag* ht[NHASH];
  400. static Tag* ft;
  401. //static Lock hlock;
  402. static ulong
  403. erendezvous(void *tag, ulong value)
  404. {
  405. int h;
  406. ulong rval;
  407. Tag *t, **l, *f;
  408. h = (ulong)tag & (NHASH-1);
  409. // lock(&hlock);
  410. pthread_mutex_lock(&rendezvouslock);
  411. l = &ht[h];
  412. for(t = ht[h]; t; t = t->next) {
  413. if(t->tag == tag) {
  414. rval = t->val;
  415. t->val = value;
  416. t->tag = 0;
  417. pthread_mutex_unlock(&rendezvouslock);
  418. // unlock(&hlock);
  419. if(pthread_cond_signal(&(t->cv)))
  420. panic("pthread_cond_signal");
  421. return rval;
  422. }
  423. }
  424. t = ft;
  425. if(t == 0) {
  426. t = malloc(sizeof(Tag));
  427. if(t == nil)
  428. panic("rendezvous: no memory");
  429. if(pthread_cond_init(&(t->cv), NULL)) {
  430. print("pthread_cond_init (errno: %s) \n", strerror(errno));
  431. panic("pthread_cond_init");
  432. }
  433. } else
  434. ft = t->next;
  435. t->tag = tag;
  436. t->val = value;
  437. t->next = *l;
  438. *l = t;
  439. // pthread_mutex_unlock(&rendezvouslock);
  440. // unlock(&hlock);
  441. while(t->tag != nil)
  442. pthread_cond_wait(&(t->cv),&rendezvouslock);
  443. // pthread_mutex_lock(&rendezvouslock);
  444. // lock(&hlock);
  445. rval = t->val;
  446. for(f = *l; f; f = f->next){
  447. if(f == t) {
  448. *l = f->next;
  449. break;
  450. }
  451. l = &f->next;
  452. }
  453. t->next = ft;
  454. ft = t;
  455. pthread_mutex_unlock(&rendezvouslock);
  456. // unlock(&hlock);
  457. return rval;
  458. }
  459. /*
  460. * Return an abitrary millisecond clock time
  461. */
  462. long
  463. osmillisec(void)
  464. {
  465. static long sec0 = 0, usec0;
  466. struct timeval t;
  467. if(gettimeofday(&t, NULL)<0)
  468. return(0);
  469. if(sec0==0) {
  470. sec0 = t.tv_sec;
  471. usec0 = t.tv_usec;
  472. }
  473. return((t.tv_sec-sec0)*1000+(t.tv_usec-usec0+500)/1000);
  474. }
  475. /*
  476. * Return the time since the epoch in nanoseconds and microseconds
  477. * The epoch is defined at 1 Jan 1970
  478. */
  479. vlong
  480. osnsec(void)
  481. {
  482. struct timeval t;
  483. gettimeofday(&t, nil);
  484. return (vlong)t.tv_sec*1000000000L + t.tv_usec*1000;
  485. }
  486. vlong
  487. osusectime(void)
  488. {
  489. struct timeval t;
  490. gettimeofday(&t, nil);
  491. return (vlong)t.tv_sec * 1000000 + t.tv_usec;
  492. }
  493. int
  494. osmillisleep(ulong milsec)
  495. {
  496. struct timespec time;
  497. time.tv_sec = milsec / 1000;
  498. time.tv_nsec = (milsec % 1000) * 1000000;
  499. nanosleep(&time, nil);
  500. return 0;
  501. }
  502. int
  503. limbosleep(ulong milsec)
  504. {
  505. return osmillisleep(milsec);
  506. }
  507. void
  508. osyield(void)
  509. {
  510. pthread_yield_np();
  511. // sched_yield();
  512. }
  513. void
  514. ospause(void)
  515. {
  516. for(;;)
  517. pause();
  518. }
  519. void
  520. oslopri(void)
  521. {
  522. // pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param);
  523. setpriority(PRIO_PROCESS, 0, getpriority(PRIO_PROCESS,0)+4);
  524. }
  525. __typeof__(sbrk(0))
  526. sbrk(int size)
  527. {
  528. void *brk;
  529. kern_return_t err;
  530. err = vm_allocate( (vm_map_t) mach_task_self(),
  531. (vm_address_t *)&brk,
  532. size,
  533. VM_FLAGS_ANYWHERE);
  534. if (err != KERN_SUCCESS)
  535. brk = (void*)-1;
  536. return brk;
  537. }