8 #include <sys/syscall.h>
14 #include <xseg/xseg.h>
16 #include <drivers/xseg_pthread.h>
20 static void *pthread_malloc(uint64_t size);
21 static void pthread_mfree(void *mem);
23 static long pthread_allocate(const char *name, uint64_t size)
26 fd = shm_open(name, O_RDWR | O_CREAT, 0770);
28 XSEGLOG("Cannot create shared segment: %s\n",
29 strerror_r(errno, errbuf, ERRSIZE));
33 r = lseek(fd, size -1, SEEK_SET);
36 XSEGLOG("Cannot seek into segment file: %s\n",
37 strerror_r(errno, errbuf, ERRSIZE));
42 r = write(fd, errbuf, 1);
45 XSEGLOG("Failed to set segment size: %s\n",
46 strerror_r(errno, errbuf, ERRSIZE));
54 static long pthread_deallocate(const char *name)
56 return shm_unlink(name);
59 static void *pthread_map(const char *name, uint64_t size, struct xseg *seg)
65 XSEGLOG("struct xseg * is not NULL. Ignoring...\n");
67 fd = shm_open(name, O_RDWR, 0000);
69 XSEGLOG("Failed to open '%s' for mapping: %s\n",
70 name, strerror_r(errno, errbuf, ERRSIZE));
74 xseg = mmap ( XSEG_BASE_AS_PTR,
76 PROT_READ | PROT_WRITE,
77 MAP_SHARED | MAP_FIXED /* | MAP_LOCKED */,
80 if (xseg == MAP_FAILED) {
81 XSEGLOG("Could not map segment: %s\n",
82 strerror_r(errno, errbuf, ERRSIZE));
90 static void pthread_unmap(void *ptr, uint64_t size)
92 struct xseg *xseg = ptr;
93 (void)munmap(xseg, xseg->segment_size);
97 static void handler(int signum)
99 static unsigned long counter;
100 printf("%lu: signal %d: this shouldn't have happened.\n", counter, signum);
104 static pthread_key_t pid_key, xpidx_key;
105 static pthread_key_t mask_key, act_key;
106 static pthread_once_t once_init = PTHREAD_ONCE_INIT;
107 static pthread_once_t once_quit = PTHREAD_ONCE_INIT;
110 static void keys_init(void)
114 r = pthread_key_create(&pid_key, NULL);
120 r = pthread_key_create(&xpidx_key, NULL);
125 r = pthread_key_create(&mask_key, NULL);
131 r = pthread_key_create(&act_key, NULL);
137 once_quit = PTHREAD_ONCE_INIT;
140 #define INT_TO_POINTER(__myptr, __myint) \
142 unsigned long __foo__ = (unsigned long) __myint; \
143 __myptr = (void *) __foo__ ; \
146 #define POINTER_TO_INT(__myint, __myptr)\
148 unsigned long __foo__ = (unsigned long) __myptr; \
149 __myint = (int) __foo__ ; \
152 /* must be called by each thread */
153 static int pthread_local_signal_init(void)
158 sigset_t *savedset, *set;
159 struct sigaction *act, *old_act;
161 savedset = pthread_malloc(sizeof(sigset_t));
164 set = pthread_malloc(sizeof(sigset_t));
168 act = pthread_malloc(sizeof(struct sigaction));
171 old_act = pthread_malloc(sizeof(struct sigaction));
175 pthread_once(&once_init, keys_init);
180 act->sa_handler = handler;
183 if(sigaction(SIGIO, act, old_act) < 0)
187 sigaddset(set, SIGIO);
189 r = pthread_sigmask(SIG_BLOCK, set, savedset);
194 pid = syscall(SYS_gettid);
195 INT_TO_POINTER(tmp, pid);
196 if (!pthread_setspecific(pid_key, tmp) ||
197 pthread_setspecific(mask_key, savedset) ||
198 pthread_setspecific(act_key, old_act))
204 pthread_sigmask(SIG_BLOCK, savedset, NULL);
206 sigaction(SIGIO, old_act, NULL);
208 pthread_mfree(old_act);
214 pthread_mfree(savedset);
219 /* should be called by each thread which had initialized signals */
220 static void pthread_local_signal_quit(void)
223 struct sigaction *old_act;
225 savedset = pthread_getspecific(act_key);
226 old_act = pthread_getspecific(mask_key);
228 sigaction(SIGIO, old_act, NULL);
230 pthread_sigmask(SIG_SETMASK, savedset, NULL);
233 static int pthread_remote_signal_init(void)
238 static void pthread_remote_signal_quit(void)
243 static int pthread_prepare_wait(struct xseg *xseg, uint32_t portno)
248 struct xseg_port *port = xseg_get_port(xseg, portno);
251 struct pthread_signal_desc *psd = xseg_get_signal_desc(xseg, port);
255 tmp = pthread_getspecific(pid_key);
256 POINTER_TO_INT(pid, tmp);
260 r = xpool_add(&psd->waiters, (xpool_index) pid, portno);
263 pthread_setspecific(xpidx_key, (void *)r);
267 static int pthread_cancel_wait(struct xseg *xseg, uint32_t portno)
272 xpool_index xpidx, r;
273 struct xseg_port *port = xseg_get_port(xseg, portno);
276 struct pthread_signal_desc *psd = xseg_get_signal_desc(xseg, port);
280 tmp = pthread_getspecific(pid_key);
281 POINTER_TO_INT(pid, tmp);
285 xpidx = (xpool_index) pthread_getspecific(xpidx_key);
287 r = xpool_remove(&psd->waiters, xpidx, &data, portno);
294 static int pthread_wait_signal(struct xseg *xseg, uint32_t usec_timeout)
301 sigaddset(&set, SIGIO);
303 ts.tv_sec = usec_timeout / 1000000;
304 ts.tv_nsec = 1000 * (usec_timeout - ts.tv_sec * 1000000);
306 r = sigtimedwait(&set, &siginfo, &ts);
310 return siginfo.si_signo;
313 static int pthread_signal(struct xseg *xseg, uint32_t portno)
318 struct xseg_port *port = xseg_get_port(xseg, portno);
321 struct pthread_signal_desc *psd = xseg_get_signal_desc(xseg, port);
325 idx = xpool_peek(&psd->waiters, &data, portno); //FIXME portno is not the caller but the callee
329 pid_t cue = (pid_t) data;
333 return syscall(SYS_tkill, cue, SIGIO);
336 static void *pthread_malloc(uint64_t size)
338 return malloc((size_t)size);
341 static void *pthread_realloc(void *mem, uint64_t size)
343 return realloc(mem, (size_t)size);
346 static void pthread_mfree(void *mem)
351 static struct xseg_type xseg_pthread = {
352 /* xseg_operations */
354 .mfree = pthread_mfree,
355 .allocate = pthread_allocate,
356 .deallocate = pthread_deallocate,
358 .unmap = pthread_unmap,
364 int pthread_init_signal_desc(struct xseg *xseg, void *sd)
366 struct pthread_signal_desc *psd = (struct pthread_signal_desc *)sd;
367 xpool_init(&psd->waiters, MAX_WAITERS, &psd->bufs);
368 xpool_clear(&psd->waiters, 1);
372 void pthread_quit_signal_desc(struct xseg *xseg, void *sd)
374 struct pthread_signal_desc *psd = (struct pthread_signal_desc *)sd;
375 xpool_clear(&psd->waiters, 1);
379 void * pthread_alloc_data(struct xseg *xseg)
381 struct xobject_h *sd_h = xseg_get_objh(xseg, MAGIC_PTHREAD_SD,
382 sizeof(struct pthread_signal_desc));
386 void pthread_free_data(struct xseg *xseg, void *data)
389 xseg_put_objh(xseg, (struct xobject_h *)data);
392 void *pthread_alloc_signal_desc(struct xseg *xseg, void *data)
394 struct xobject_h *sd_h = (struct xobject_h *) data;
397 struct pthread_signal_desc *psd = xobj_get_obj(sd_h, X_ALLOC);
404 void pthread_free_signal_desc(struct xseg *xseg, void *data, void *sd)
406 struct xobject_h *sd_h = (struct xobject_h *) data;
410 xobj_put_obj(sd_h, sd);
415 static struct xseg_peer xseg_peer_pthread = {
416 /* xseg_peer_operations */
418 .init_signal_desc = pthread_init_signal_desc,
419 .quit_signal_desc = pthread_quit_signal_desc,
420 .alloc_data = pthread_alloc_data,
421 .free_data = pthread_free_data,
422 .alloc_signal_desc = pthread_alloc_signal_desc,
423 .free_signal_desc = pthread_free_signal_desc,
424 .local_signal_init = pthread_local_signal_init,
425 .local_signal_quit = pthread_local_signal_quit,
426 .remote_signal_init = pthread_remote_signal_init,
427 .remote_signal_quit = pthread_remote_signal_quit,
428 .prepare_wait = pthread_prepare_wait,
429 .cancel_wait = pthread_cancel_wait,
430 .wait_signal = pthread_wait_signal,
431 .signal = pthread_signal,
432 .malloc = pthread_malloc,
433 .realloc = pthread_realloc,
434 .mfree = pthread_mfree,
440 void xseg_pthread_init(void)
442 xseg_register_type(&xseg_pthread);
443 xseg_register_peer(&xseg_peer_pthread);