mirror of
https://github.com/golang/go
synced 2024-11-23 00:40:08 -07:00
only use mach kernel semaphores for actual contention.
running rob's powser p.go: 3.21u 2.58s 5.80r 6.out # old 1.48u 0.05s 1.54r 6.out # new R=r OCL=15748 CL=15750
This commit is contained in:
parent
eea21f8b85
commit
5ff12f871f
@ -262,7 +262,7 @@ xadd(uint32 volatile *val, int32 delta)
|
|||||||
// releases the lock by decrementing l->key, l->key will
|
// releases the lock by decrementing l->key, l->key will
|
||||||
// be >0, so it will increment the semaphore to wake up
|
// be >0, so it will increment the semaphore to wake up
|
||||||
// one of the others. This is the same algorithm used
|
// one of the others. This is the same algorithm used
|
||||||
// in Plan 9's user-space locks.
|
// in Plan 9's user-level locks.
|
||||||
//
|
//
|
||||||
// Note that semaphores are never destroyed (the kernel
|
// Note that semaphores are never destroyed (the kernel
|
||||||
// will clean up when the process exits). We assume for now
|
// will clean up when the process exits). We assume for now
|
||||||
@ -287,6 +287,25 @@ unlock(Lock *l)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// User-level semaphore implementation:
|
||||||
|
// try to do the operations in user space on u,
|
||||||
|
// but when it's time to block, fall back on the kernel semaphore k.
|
||||||
|
// This is the same algorithm used in Plan 9.
|
||||||
|
void
|
||||||
|
usemacquire(Usema *s)
|
||||||
|
{
|
||||||
|
if((int32)xadd(&s->u, -1) < 0)
|
||||||
|
semacquire(s->k);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
usemrelease(Usema *s)
|
||||||
|
{
|
||||||
|
if((int32)xadd(&s->u, 1) <= 0)
|
||||||
|
semrelease(s->k);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Event notifications.
|
// Event notifications.
|
||||||
void
|
void
|
||||||
noteclear(Note *n)
|
noteclear(Note *n)
|
||||||
@ -297,19 +316,19 @@ noteclear(Note *n)
|
|||||||
void
|
void
|
||||||
notesleep(Note *n)
|
notesleep(Note *n)
|
||||||
{
|
{
|
||||||
if(n->sema == 0)
|
if(n->sema.k == 0)
|
||||||
initsema(&n->sema);
|
initsema(&n->sema.k);
|
||||||
while(!n->wakeup)
|
while(!n->wakeup)
|
||||||
semacquire(n->sema);
|
usemacquire(&n->sema);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
notewakeup(Note *n)
|
notewakeup(Note *n)
|
||||||
{
|
{
|
||||||
if(n->sema == 0)
|
if(n->sema.k == 0)
|
||||||
initsema(&n->sema);
|
initsema(&n->sema.k);
|
||||||
n->wakeup = 1;
|
n->wakeup = 1;
|
||||||
semrelease(n->sema);
|
usemrelease(&n->sema);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ typedef struct Alg Alg;
|
|||||||
typedef struct Lock Lock;
|
typedef struct Lock Lock;
|
||||||
typedef union Note Note;
|
typedef union Note Note;
|
||||||
typedef struct Mem Mem;
|
typedef struct Mem Mem;
|
||||||
|
typedef struct Usema Usema;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* per cpu declaration
|
* per cpu declaration
|
||||||
@ -77,6 +78,11 @@ struct Lock
|
|||||||
uint32 key;
|
uint32 key;
|
||||||
uint32 sema; // for OS X
|
uint32 sema; // for OS X
|
||||||
};
|
};
|
||||||
|
struct Usema
|
||||||
|
{
|
||||||
|
uint32 u;
|
||||||
|
uint32 k;
|
||||||
|
};
|
||||||
union Note
|
union Note
|
||||||
{
|
{
|
||||||
struct { // Linux
|
struct { // Linux
|
||||||
@ -84,7 +90,7 @@ union Note
|
|||||||
};
|
};
|
||||||
struct { // OS X
|
struct { // OS X
|
||||||
int32 wakeup;
|
int32 wakeup;
|
||||||
uint32 sema;
|
Usema sema;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
struct String
|
struct String
|
||||||
|
Loading…
Reference in New Issue
Block a user