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

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

#line 24 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
typedef struct Sema Sema; 
struct Sema 
{ 
uint32 volatile* addr; 
G* g; 
int64 releasetime; 
Sema* prev; 
Sema* next; 
} ; 
#line 34 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
typedef struct SemaRoot SemaRoot; 
struct SemaRoot 
{ 
Lock; 
Sema* head; 
Sema* tail; 
#line 41 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
uint32 volatile nwait; 
} ; 
#line 45 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
#define SEMTABLESZ 251 
#line 47 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
struct semtable 
{ 
SemaRoot; 
uint8 pad[CacheLineSize-sizeof ( SemaRoot ) ]; 
} ; 
#pragma dataflag 16 
static struct semtable semtable[SEMTABLESZ]; 
#line 55 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
static SemaRoot* 
semroot ( uint32 *addr ) 
{ 
return &semtable[ ( ( uintptr ) addr >> 3 ) % SEMTABLESZ]; 
} 
#line 61 "/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 75 "/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 90 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
static int32 
cansemacquire ( uint32 *addr ) 
{ 
uint32 v; 
#line 95 "/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 101 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
static void 
semacquireimpl ( uint32 volatile *addr , int32 profile ) 
{ 
Sema s; 
SemaRoot *root; 
int64 t0; 
#line 109 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
if ( cansemacquire ( addr ) ) 
return; 
#line 118 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
root = semroot ( addr ) ; 
t0 = 0; 
s.releasetime = 0; 
if ( profile && runtime·blockprofilerate > 0 ) { 
t0 = runtime·cputicks ( ) ; 
s.releasetime = -1; 
} 
for ( ;; ) { 
runtime·lock ( root ) ; 
#line 128 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
runtime·xadd ( &root->nwait , 1 ) ; 
#line 130 "/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 137 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
semqueue ( root , addr , &s ) ; 
runtime·park ( runtime·unlock , root , "semacquire" ) ; 
if ( cansemacquire ( addr ) ) { 
if ( t0 ) 
runtime·blockevent ( s.releasetime - t0 , 3 ) ; 
return; 
} 
} 
} 
#line 147 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
void 
runtime·semacquire ( uint32 volatile *addr ) 
{ 
semacquireimpl ( addr , 0 ) ; 
} 
#line 153 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
void 
runtime·semrelease ( uint32 volatile *addr ) 
{ 
Sema *s; 
SemaRoot *root; 
#line 159 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
root = semroot ( addr ) ; 
runtime·xadd ( addr , 1 ) ; 
#line 165 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
if ( runtime·atomicload ( &root->nwait ) == 0 ) 
return; 
#line 169 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"
runtime·lock ( root ) ; 
if ( runtime·atomicload ( &root->nwait ) == 0 ) { 
#line 173 "/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 ) { 
if ( s->releasetime ) 
s->releasetime = runtime·cputicks ( ) ; 
runtime·ready ( s->g ) ; 
} 
} 
void
sync·runtime_Semacquire(uint32* addr)
{
#line 191 "/wrkdirs/usr/ports/lang/go/work/go/src/pkg/runtime/sema.goc"

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

	runtime·semrelease(addr);
}
