lkml.org 
[lkml]   [2002]   [Mar]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: [PATCH] Futexes IV (Fast Lightweight Userspace Semaphores)
Rusty Russell wrote:

> On Mon, 25 Mar 2002 13:28:44 +1100
> Rusty Russell <rusty@rustcorp.com.au> wrote:
>
>>So the summary is: futexes not sufficient to implement pthreads
>>locking.
>>
>
> So let's go back to the more generic "exporting waitqueues to userspace" idea,
> with a twist: we use a userspace address as the identifier on the waitq, which
> gives us a unique identifier, but the kernel never actually derefs the
> pointer. (And in my prior kernel code I optimized it so that waking did an
> implicit remove; not sure it's a win, so assumed that was removed here).
>
> This gives code as below (Peter, Martin, please check):
>
> /* Assume we have the following operations:
>
> uwaitq_add(void *uaddr);
> uwaitq_remove(void *uaddr);
> uwaitq_wake(void *uaddr, int wake_all_flag);
> uwaitq_wait(relative timeout);
> */
> typedef struct
> {
> int counter;
> } pthread_mutex_t;
>
> typedef struct
> {
> int condition;
> } pthread_cond_t;
>

> int pthread_cond_signal(pthread_cond_t *cond)
> {
> return uwaitq_wake(cond, 0 /* WAKE_ONE */);
> }
>
> int pthread_cond_broadcast(pthread_cond_t *cond)
> {
> return uwaitq_wake(cond, 1 /* WAKE_ALL */);
> }
>
> static int __pthread_cond_wait(pthread_cond_t *cond,
> pthread_mutex_t *mutex,
> const struct timespec *reltime)
> {
> int ret;
>
> uwaitq_add(cond);
> futex_up(&mutex, 1);


Here another thread gets scheduled, calling signal/broadcast.
Since the former thread is already on the queue -> well done ;-)


> while ((ret = uwaitq_wait(reltime)) == 0 || errno == EINTR);
> uwaitq_remove(cond);
> futex_down(&mutex, NULL);
> return ret;
> }


I assume that uwaitq_wait() will modify the reltime (which is legal)
if signalled. Otherwise we would wait 2*retime, and so on

Then we have to be careful about errno and the return values:

static int __pthread_cond_wait(pthread_cond_t *cond,
pthread_mutex_t *mutex,
const struct timespec *reltime)
{
int ret;

!
if (uwaitq_add(cond) == -1)
+
return -1;
!
if (futex_up(&mutex, 1) == -1){
+
uwaitq_remove(cond);
+
return -1;
+
}
!
while ((ret = uwaitq_wait(cond,reltime)) == -1 && errno == EINTR);
+
saverrno=errno;
uwaitq_remove(cond);
futex_down(&mutex, NULL);
+
if (ret == -1){
+
if (saverrno == ENOENT)
+
return 0; /* there was a sig/broadc before we went to sleep*/
+
errno=saverrno;
+
return -1;
+
}
return 0;
}

I assume that uwaitq_wait() will return -1 and errno==ENOENT or similar
if we are not on the queue (anymore), -1 and ETIMEDOUT on timeout,
-1 and EINVAL on illegal cond or reltime ,zero on wakeup?


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:25    [W:0.077 / U:0.296 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site