// auto generated by go tool dist
// goos=freebsd goarch=amd64

#include "runtime.h"
#include "arch_GOARCH.h"

#line 970 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
typedef struct Sema Sema; 
struct Sema 
{ 
uint32 volatile *addr; 
G *g; 
Sema *prev; 
Sema *next; 
} ; 
#line 979 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
typedef struct SemaRoot SemaRoot; 
struct SemaRoot 
{ 
Lock; 
Sema *head; 
Sema *tail; 
#line 986 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
uint32 volatile nwait; 
} ; 
#line 990 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
#define SEMTABLESZ 251 
#line 992 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
static union 
{ 
SemaRoot; 
uint8 pad[CacheLineSize]; 
} semtable[SEMTABLESZ]; 
#line 998 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
static SemaRoot* 
semroot ( uint32 *addr ) 
{ 
return &semtable[ ( ( uintptr ) addr >> 3 ) % SEMTABLESZ]; 
} 
#line 1004 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
static void 
semqueue ( SemaRoot *root , uint32 volatile *addr , Sema *s ) 
{ 
s->g = g; 
s->addr = addr; 
s->next = nil; 
s->prev = root->tail; 
if ( root->tail ) 
root->tail->next = s; 
else 
root->head = s; 
root->tail = s; 
} 
#line 1018 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
static void 
semdequeue ( SemaRoot *root , Sema *s ) 
{ 
if ( s->next ) 
s->next->prev = s->prev; 
else 
root->tail = s->prev; 
if ( s->prev ) 
s->prev->next = s->next; 
else 
root->head = s->next; 
s->prev = nil; 
s->next = nil; 
} 
#line 1033 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
static int32 
cansemacquire ( uint32 *addr ) 
{ 
uint32 v; 
#line 1038 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
while ( ( v = runtime·atomicload ( addr ) ) > 0 ) 
if ( runtime·cas ( addr , v , v-1 ) ) 
return 1; 
return 0; 
} 
#line 1044 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
void 
runtime·semacquire ( uint32 volatile *addr ) 
{ 
Sema s; 
SemaRoot *root; 
#line 1051 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
if ( cansemacquire ( addr ) ) 
return; 
#line 1060 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
root = semroot ( addr ) ; 
for ( ;; ) { 
runtime·lock ( root ) ; 
#line 1064 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
runtime·xadd ( &root->nwait , 1 ) ; 
#line 1066 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
if ( cansemacquire ( addr ) ) { 
runtime·xadd ( &root->nwait , -1 ) ; 
runtime·unlock ( root ) ; 
return; 
} 
#line 1073 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
semqueue ( root , addr , &s ) ; 
g->status = Gwaiting; 
g->waitreason = "semacquire" ; 
runtime·unlock ( root ) ; 
runtime·gosched ( ) ; 
if ( cansemacquire ( addr ) ) 
return; 
} 
} 
#line 1083 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
void 
runtime·semrelease ( uint32 volatile *addr ) 
{ 
Sema *s; 
SemaRoot *root; 
#line 1089 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
root = semroot ( addr ) ; 
runtime·xadd ( addr , 1 ) ; 
#line 1095 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
if ( runtime·atomicload ( &root->nwait ) == 0 ) 
return; 
#line 1099 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
runtime·lock ( root ) ; 
if ( runtime·atomicload ( &root->nwait ) == 0 ) { 
#line 1103 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
runtime·unlock ( root ) ; 
return; 
} 
for ( s = root->head; s; s = s->next ) { 
if ( s->addr == addr ) { 
runtime·xadd ( &root->nwait , -1 ) ; 
semdequeue ( root , s ) ; 
break; 
} 
} 
runtime·unlock ( root ) ; 
if ( s ) 
runtime·ready ( s->g ) ; 
} 
void
sync·runtime_Semacquire(uint32* addr)
{
#line 1118 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"

	runtime·semacquire(addr);
}
void
sync·runtime_Semrelease(uint32* addr)
{
#line 1122 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"

	runtime·semrelease(addr);
}
