From a3ffb06619416e08b49afaaa4638be212aaa04da Mon Sep 17 00:00:00 2001 From: Filippos Giannakos Date: Thu, 14 Mar 2013 11:20:42 +0200 Subject: [PATCH] Improve pthread signaling. Remove xpool data type that required a lock on insertion / on seek and replace it by an array of pids. On the array of pids, each thread place its pid in his own reserved entry. Any one who wishes to signal a pthread peer, checks that array for a valid pid. --- xseg/drivers/kernel/xseg_pthread.c | 18 ++++--- xseg/drivers/user/xseg_pthread.c | 92 ++++++++++++++++++++---------------- xseg/drivers/xseg_pthread.h | 5 +- 3 files changed, 66 insertions(+), 49 deletions(-) diff --git a/xseg/drivers/kernel/xseg_pthread.c b/xseg/drivers/kernel/xseg_pthread.c index 674b00d..395ecd8 100644 --- a/xseg/drivers/kernel/xseg_pthread.c +++ b/xseg/drivers/kernel/xseg_pthread.c @@ -86,10 +86,10 @@ static int pthread_wait_signal(struct xseg *xseg, uint32_t timeout) static int pthread_signal(struct xseg *xseg, uint32_t portno) { struct pid *pid; + int i; + pid_t cue = 0; struct task_struct *task; int ret = -ENOENT; - xpool_data data; - xpool_index idx; struct pthread_signal_desc *psd; struct xseg_port *port = xseg_get_port(xseg, portno); if (!port) @@ -100,14 +100,20 @@ static int pthread_signal(struct xseg *xseg, uint32_t portno) rcu_read_lock(); /* XXX Security: xseg peers can kill anyone */ - idx = xpool_peek(&psd->waiters, &data, portno); //FIXME portno is not the caller but the callee - if (idx == NoIndex){ - /* no waiters */ + + for (i = 0; i < MAX_WAITERS; i++) { + cue = psd->pids[i]; + if (cue) + break; + } + if (!cue){ + /* no waiters found */ ret = 0; goto out; } - pid = find_vpid((pid_t) data); + + pid = find_vpid(cue); if (!pid) goto out; task = pid_task(pid, PIDTYPE_PID); diff --git a/xseg/drivers/user/xseg_pthread.c b/xseg/drivers/user/xseg_pthread.c index d1ddc98..8c6ddd9 100644 --- a/xseg/drivers/user/xseg_pthread.c +++ b/xseg/drivers/user/xseg_pthread.c @@ -137,20 +137,22 @@ static void handler(int signum) static pthread_key_t pid_key, xpidx_key; static pthread_key_t mask_key, act_key; +static pthread_key_t id_key; static pthread_once_t once_init = PTHREAD_ONCE_INIT; static pthread_once_t once_quit = PTHREAD_ONCE_INIT; static int isInit; +static volatile int id = 0; -static void keys_init(void) +static void keys_init(void) { int r; - + r = pthread_key_create(&pid_key, NULL); if (r < 0) { isInit = 0; return; } - + r = pthread_key_create(&xpidx_key, NULL); if (r < 0) { isInit = 0; @@ -161,34 +163,39 @@ static void keys_init(void) isInit = 0; return; } - + r = pthread_key_create(&act_key, NULL); if (r < 0) { isInit = 0; return; } + r = pthread_key_create(&id_key, NULL); + if (r < 0) { + isInit = 0; + return; + } isInit = 1; once_quit = PTHREAD_ONCE_INIT; } #define INT_TO_POINTER(__myptr, __myint) \ do {\ - unsigned long __foo__ = (unsigned long) __myint; \ - __myptr = (void *) __foo__ ; \ + unsigned long __foo____myptr = (unsigned long) __myint; \ + __myptr = (void *) __foo____myptr ; \ } while (0) #define POINTER_TO_INT(__myint, __myptr)\ do { \ - unsigned long __foo__ = (unsigned long) __myptr; \ - __myint = (int) __foo__ ; \ + unsigned long __foo____myint = (unsigned long) __myptr; \ + __myint = (int) __foo____myint ; \ } while (0) /* must be called by each thread */ static int pthread_local_signal_init(struct xseg *xseg, xport portno) { - int r; + int r, my_id; pid_t pid; - void *tmp; + void *tmp, *tmp2; sigset_t *savedset, *set; struct sigaction *act, *old_act; @@ -225,11 +232,17 @@ static int pthread_local_signal_init(struct xseg *xseg, xport portno) goto err6; + my_id = *(volatile int *) &id; + while (!__sync_bool_compare_and_swap(&id, my_id, my_id+1)){ + my_id = *(volatile int *) &id; + } pid = syscall(SYS_gettid); INT_TO_POINTER(tmp, pid); - if (!pthread_setspecific(pid_key, tmp) || + INT_TO_POINTER(tmp2, my_id); + if (pthread_setspecific(pid_key, tmp) || pthread_setspecific(mask_key, savedset) || - pthread_setspecific(act_key, old_act)) + pthread_setspecific(act_key, old_act) || + pthread_setspecific(id_key, tmp2)) goto err7; return 0; @@ -278,7 +291,7 @@ static int pthread_prepare_wait(struct xseg *xseg, uint32_t portno) { void * tmp; pid_t pid; - xpool_index r; + int my_id; struct xseg_port *port = xseg_get_port(xseg, portno); if (!port) return -1; @@ -290,38 +303,33 @@ static int pthread_prepare_wait(struct xseg *xseg, uint32_t portno) POINTER_TO_INT(pid, tmp); if (!pid) return -1; - - r = xpool_add(&psd->waiters, (xpool_index) pid, portno); - if (r == NoIndex) - return -1; - pthread_setspecific(xpidx_key, (void *)r); + tmp = pthread_getspecific(id_key); + POINTER_TO_INT(my_id, tmp); + psd->pids[my_id] = pid; return 0; } static int pthread_cancel_wait(struct xseg *xseg, uint32_t portno) { void * tmp; + int my_id; pid_t pid; - xpool_data data; - xpool_index xpidx, r; struct xseg_port *port = xseg_get_port(xseg, portno); - if (!port) + if (!port) return -1; struct pthread_signal_desc *psd = xseg_get_signal_desc(xseg, port); if (!psd) return -1; - + tmp = pthread_getspecific(pid_key); POINTER_TO_INT(pid, tmp); if (!pid) return -1; - xpidx = (xpool_index) pthread_getspecific(xpidx_key); + tmp = pthread_getspecific(id_key); + POINTER_TO_INT(my_id, tmp); + psd->pids[my_id] = 0; - r = xpool_remove(&psd->waiters, xpidx, &data, portno); - if (r == NoIndex) - return -1; - return 0; } @@ -346,8 +354,7 @@ static int pthread_wait_signal(struct xseg *xseg, uint32_t usec_timeout) static int pthread_signal(struct xseg *xseg, uint32_t portno) { - xpool_data data; - xpool_index idx; + int i; struct xseg_port *port = xseg_get_port(xseg, portno); if (!port) @@ -356,15 +363,15 @@ static int pthread_signal(struct xseg *xseg, uint32_t portno) if (!psd) return -1; - idx = xpool_peek(&psd->waiters, &data, portno); //FIXME portno is not the caller but the callee - if (idx == NoIndex) - return 0; - - pid_t cue = (pid_t) data; - if (!cue) - return 0; + pid_t cue; + for (i = 0; i < MAX_WAITERS; i++) { + cue = psd->pids[i]; + if (cue) + return syscall(SYS_tkill, cue, SIGIO); + } - return syscall(SYS_tkill, cue, SIGIO); + /* no waiter found */ + return 0; } static void *pthread_malloc(uint64_t size) @@ -397,16 +404,21 @@ static struct xseg_type xseg_pthread = { int pthread_init_signal_desc(struct xseg *xseg, void *sd) { + int i; struct pthread_signal_desc *psd = (struct pthread_signal_desc *)sd; - xpool_init(&psd->waiters, MAX_WAITERS, psd->bufs); - xpool_clear(&psd->waiters, 1); + for (i = 0; i < MAX_WAITERS; i++) { + psd->pids[i]=0; + } return 0; } void pthread_quit_signal_desc(struct xseg *xseg, void *sd) { + int i; struct pthread_signal_desc *psd = (struct pthread_signal_desc *)sd; - xpool_clear(&psd->waiters, 1); + for (i = 0; i < MAX_WAITERS; i++) { + psd->pids[i]=0; + } return; } diff --git a/xseg/drivers/xseg_pthread.h b/xseg/drivers/xseg_pthread.h index cebc106..07f2b26 100644 --- a/xseg/drivers/xseg_pthread.h +++ b/xseg/drivers/xseg_pthread.h @@ -38,6 +38,5 @@ #define MAGIC_PTHREAD_SD 7 struct pthread_signal_desc{ - struct xpool waiters; - struct xpool_node bufs[MAX_WAITERS]; -}; + volatile pid_t pids[MAX_WAITERS]; +}; -- 1.7.10.4