8 #include <sys/syscall.h>
14 #include <xseg/xseg.h>
20 static long pthread_allocate(const char *name, uint64_t size)
23 fd = shm_open(name, O_RDWR | O_CREAT, 0770);
25 XSEGLOG("Cannot create shared segment: %s\n",
26 strerror_r(errno, errbuf, ERRSIZE));
30 r = lseek(fd, size -1, SEEK_SET);
33 XSEGLOG("Cannot seek into segment file: %s\n",
34 strerror_r(errno, errbuf, ERRSIZE));
39 r = write(fd, errbuf, 1);
42 XSEGLOG("Failed to set segment size: %s\n",
43 strerror_r(errno, errbuf, ERRSIZE));
51 static long pthread_deallocate(const char *name)
53 return shm_unlink(name);
56 static void *pthread_map(const char *name, uint64_t size, struct xseg *seg)
62 XSEGLOG("struct xseg * is not NULL. Ignoring...\n");
64 fd = shm_open(name, O_RDWR, 0000);
66 XSEGLOG("Failed to open '%s' for mapping: %s\n",
67 name, strerror_r(errno, errbuf, ERRSIZE));
71 xseg = mmap ( XSEG_BASE_AS_PTR,
73 PROT_READ | PROT_WRITE,
74 MAP_SHARED | MAP_FIXED /* | MAP_LOCKED */,
77 if (xseg == MAP_FAILED) {
78 XSEGLOG("Could not map segment: %s\n",
79 strerror_r(errno, errbuf, ERRSIZE));
87 static void pthread_unmap(void *ptr, uint64_t size)
89 struct xseg *xseg = ptr;
90 (void)munmap(xseg, xseg->segment_size);
94 static void handler(int signum)
96 static unsigned long counter;
97 printf("%lu: signal %d: this shouldn't have happened.\n", counter, signum);
101 static sigset_t savedset, set;
102 static pthread_key_t key;
103 static pthread_once_t once_init = PTHREAD_ONCE_INIT;
104 static pthread_once_t once_quit = PTHREAD_ONCE_INIT;
107 static void signal_init(void)
111 h = signal(SIGIO, handler);
118 sigaddset(&set, SIGIO);
120 r = pthread_sigmask(SIG_BLOCK, &set, &savedset);
126 r = pthread_key_create(&key, NULL);
132 once_quit = PTHREAD_ONCE_INIT;
135 static void signal_quit(void)
137 pthread_key_delete(key);
138 signal(SIGIO, SIG_DFL);
139 pthread_sigmask(SIG_SETMASK, &savedset, NULL);
141 once_init = PTHREAD_ONCE_INIT;
144 #define INT_TO_POINTER(__myptr, __myint) \
146 unsigned long __foo__ = (unsigned long) __myint; \
147 __myptr = (void *) __foo__ ; \
150 #define POINTER_TO_INT(__myint, __myptr)\
152 unsigned long __foo__ = (unsigned long) __myptr; \
153 __myint = (int) __foo__ ; \
156 /* must be called by each thread */
157 static int pthread_signal_init(void)
162 pthread_once(&once_init, signal_init);
165 pid = syscall(SYS_gettid);
166 INT_TO_POINTER(tmp, pid);
167 r = pthread_setspecific(key, tmp);
171 /* can be called by each thread */
172 static void pthread_signal_quit(void)
174 pthread_once(&once_quit, signal_quit);
177 static int pthread_prepare_wait(struct xseg *xseg, uint32_t portno)
181 struct xseg_port *port = xseg_get_port(xseg, portno);
185 tmp = pthread_getspecific(key);
186 POINTER_TO_INT(pid, tmp);
190 xpool_add(&port->waiters, (xpool_index) pid, portno);
194 static int pthread_cancel_wait(struct xseg *xseg, uint32_t portno)
199 struct xseg_port *port = xseg_get_port(xseg, portno);
203 tmp = pthread_getspecific(key);
204 POINTER_TO_INT(pid, tmp);
208 xpool_remove(&port->waiters, (xpool_index) pid, &data, portno);
212 static int pthread_wait_signal(struct xseg *xseg, uint32_t usec_timeout)
218 ts.tv_sec = usec_timeout / 1000000;
219 ts.tv_nsec = 1000 * (usec_timeout - ts.tv_sec * 1000000);
221 /* FIXME: Now that pthread signaling is fixed, we could get rid of the timeout
222 * and use a NULL timespec linux-specific)
224 r = sigtimedwait(&set, &siginfo, &ts);
228 return siginfo.si_signo;
231 static int pthread_signal(struct xseg *xseg, uint32_t portno)
236 struct xseg_port *port = xseg_get_port(xseg, portno);
240 idx = xpool_peek(&port->waiters, &data, portno); //FIXME portno is not the caller but the callee
244 pid_t cue = (pid_t) data;
248 return syscall(SYS_tkill, cue, SIGIO);
251 static void *pthread_malloc(uint64_t size)
253 return malloc((size_t)size);
256 static void *pthread_realloc(void *mem, uint64_t size)
258 return realloc(mem, (size_t)size);
261 static void pthread_mfree(void *mem)
266 static struct xseg_type xseg_pthread = {
267 /* xseg_operations */
269 .mfree = pthread_mfree,
270 .allocate = pthread_allocate,
271 .deallocate = pthread_deallocate,
273 .unmap = pthread_unmap,
279 static struct xseg_peer xseg_peer_pthread = {
280 /* xseg_peer_operations */
282 .signal_init = pthread_signal_init,
283 .signal_quit = pthread_signal_quit,
284 .prepare_wait = pthread_prepare_wait,
285 .cancel_wait = pthread_cancel_wait,
286 .wait_signal = pthread_wait_signal,
287 .signal = pthread_signal,
288 .malloc = pthread_malloc,
289 .realloc = pthread_realloc,
290 .mfree = pthread_mfree,
296 void xseg_pthread_init(void)
298 xseg_register_type(&xseg_pthread);
299 xseg_register_peer(&xseg_peer_pthread);