Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
376898ca
Commit
376898ca
authored
Sep 09, 2008
by
Russ Cox
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
go threads for OS X
R=r OCL=14944 CL=15013
parent
c59d2f13
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
208 additions
and
52 deletions
+208
-52
amd64_darwin.h
src/runtime/amd64_darwin.h
+21
-0
amd64_linux.h
src/runtime/amd64_linux.h
+1
-1
chan.c
src/runtime/chan.c
+29
-23
proc.c
src/runtime/proc.c
+1
-3
rt0_amd64.s
src/runtime/rt0_amd64.s
+1
-0
rt1_amd64_darwin.c
src/runtime/rt1_amd64_darwin.c
+0
-0
rt1_amd64_linux.c
src/runtime/rt1_amd64_linux.c
+4
-0
runtime.h
src/runtime/runtime.h
+12
-5
sys_amd64_darwin.s
src/runtime/sys_amd64_darwin.s
+130
-5
sys_amd64_linux.s
src/runtime/sys_amd64_linux.s
+9
-15
No files found.
src/runtime/amd64_darwin.h
View file @
376898ca
...
...
@@ -22,6 +22,11 @@ struct timespec {
int64
tv_nsec
;
};
struct
timeval
{
time_t
tv_sec
;
int64
tv_usec
;
};
struct
stat
{
// really a stat64
dev_t
st_dev
;
mode_t
st_mode
;
...
...
@@ -43,3 +48,19 @@ struct stat { // really a stat64
};
#define O_CREAT 0x0200
void
bsdthread_create
(
void
*
,
M
*
,
G
*
,
void
(
*
)(
void
));
void
bsdthread_register
(
void
);
int64
select
(
int32
,
void
*
,
void
*
,
void
*
,
struct
timeval
*
);
// Mach calls
typedef
int32
kern_return_t
;
typedef
uint32
mach_port_t
;
mach_port_t
semcreate
(
void
);
void
semacquire
(
mach_port_t
);
void
semrelease
(
mach_port_t
);
void
semreset
(
mach_port_t
);
void
semdestroy
(
mach_port_t
);
src/runtime/amd64_linux.h
View file @
376898ca
...
...
@@ -49,5 +49,5 @@ struct stat {
// Linux-specific system calls
int64
futex
(
uint32
*
,
int32
,
uint32
,
struct
timespec
*
,
uint32
*
,
uint32
);
int64
clone
(
int32
,
void
*
,
M
*
,
G
*
,
void
(
*
)(
void
));
int64
select
(
int32
,
void
*
,
void
*
,
void
*
,
void
*
);
int64
select
(
int32
,
void
*
,
void
*
,
void
*
,
struct
timeval
*
);
src/runtime/chan.c
View file @
376898ca
...
...
@@ -4,9 +4,8 @@
#include "runtime.h"
// TODO locking of select
static
int32
debug
=
0
;
static
Lock
chanlock
;
typedef
struct
Hchan
Hchan
;
typedef
struct
Link
Link
;
...
...
@@ -32,7 +31,6 @@ struct WaitQ
struct
Hchan
{
Lock
;
uint32
elemsize
;
uint32
dataqsiz
;
// size of the circular q
uint32
qcount
;
// total data in the q
...
...
@@ -162,7 +160,7 @@ sendchan(Hchan *c, byte *ep, bool *pres)
prints
(
"
\n
"
);
}
lock
(
c
);
lock
(
&
chanlock
);
if
(
c
->
dataqsiz
>
0
)
goto
asynch
;
...
...
@@ -173,7 +171,7 @@ sendchan(Hchan *c, byte *ep, bool *pres)
gp
=
sg
->
g
;
gp
->
param
=
sg
;
unlock
(
c
);
unlock
(
&
chanlock
);
ready
(
gp
);
if
(
pres
!=
nil
)
...
...
@@ -182,7 +180,7 @@ sendchan(Hchan *c, byte *ep, bool *pres)
}
if
(
pres
!=
nil
)
{
unlock
(
c
);
unlock
(
&
chanlock
);
*
pres
=
false
;
return
;
}
...
...
@@ -193,13 +191,13 @@ sendchan(Hchan *c, byte *ep, bool *pres)
g
->
param
=
nil
;
g
->
status
=
Gwaiting
;
enqueue
(
&
c
->
sendq
,
sg
);
unlock
(
c
);
unlock
(
&
chanlock
);
sys
·
gosched
();
lock
(
c
);
lock
(
&
chanlock
);
sg
=
g
->
param
;
freesg
(
c
,
sg
);
unlock
(
c
);
unlock
(
&
chanlock
);
return
;
asynch
:
...
...
@@ -208,9 +206,9 @@ asynch:
sg
=
allocsg
(
c
);
g
->
status
=
Gwaiting
;
enqueue
(
&
c
->
sendq
,
sg
);
unlock
(
c
);
unlock
(
&
chanlock
);
sys
·
gosched
();
lock
(
c
);
lock
(
&
chanlock
);
}
if
(
ep
!=
nil
)
c
->
elemalg
->
copy
(
c
->
elemsize
,
c
->
senddataq
->
elem
,
ep
);
...
...
@@ -221,10 +219,10 @@ asynch:
if
(
sg
!=
nil
)
{
gp
=
sg
->
g
;
freesg
(
c
,
sg
);
unlock
(
c
);
unlock
(
&
chanlock
);
ready
(
gp
);
}
else
unlock
(
c
);
unlock
(
&
chanlock
);
}
static
void
...
...
@@ -239,7 +237,7 @@ chanrecv(Hchan* c, byte *ep, bool* pres)
prints
(
"
\n
"
);
}
lock
(
c
);
lock
(
&
chanlock
);
if
(
c
->
dataqsiz
>
0
)
goto
asynch
;
...
...
@@ -249,7 +247,7 @@ chanrecv(Hchan* c, byte *ep, bool* pres)
gp
=
sg
->
g
;
gp
->
param
=
sg
;
unlock
(
c
);
unlock
(
&
chanlock
);
ready
(
gp
);
if
(
pres
!=
nil
)
...
...
@@ -258,7 +256,7 @@ chanrecv(Hchan* c, byte *ep, bool* pres)
}
if
(
pres
!=
nil
)
{
unlock
(
c
);
unlock
(
&
chanlock
);
*
pres
=
false
;
return
;
}
...
...
@@ -267,14 +265,14 @@ chanrecv(Hchan* c, byte *ep, bool* pres)
g
->
param
=
nil
;
g
->
status
=
Gwaiting
;
enqueue
(
&
c
->
recvq
,
sg
);
unlock
(
c
);
unlock
(
&
chanlock
);
sys
·
gosched
();
lock
(
c
);
lock
(
&
chanlock
);
sg
=
g
->
param
;
c
->
elemalg
->
copy
(
c
->
elemsize
,
ep
,
sg
->
elem
);
freesg
(
c
,
sg
);
unlock
(
c
);
unlock
(
&
chanlock
);
return
;
asynch
:
...
...
@@ -282,9 +280,9 @@ asynch:
sg
=
allocsg
(
c
);
g
->
status
=
Gwaiting
;
enqueue
(
&
c
->
recvq
,
sg
);
unlock
(
c
);
unlock
(
&
chanlock
);
sys
·
gosched
();
lock
(
c
);
lock
(
&
chanlock
);
}
c
->
elemalg
->
copy
(
c
->
elemsize
,
ep
,
c
->
recvdataq
->
elem
);
c
->
recvdataq
=
c
->
recvdataq
->
link
;
...
...
@@ -293,10 +291,10 @@ asynch:
if
(
sg
!=
nil
)
{
gp
=
sg
->
g
;
freesg
(
c
,
sg
);
unlock
(
c
);
unlock
(
&
chanlock
);
ready
(
gp
);
}
else
unlock
(
c
);
unlock
(
&
chanlock
);
}
// chansend1(hchan *chan any, elem any);
...
...
@@ -371,12 +369,14 @@ sys·newselect(int32 size, Select *sel)
if
(
size
>
1
)
n
=
size
-
1
;
lock
(
&
chanlock
);
sel
=
nil
;
if
(
size
>=
1
&&
size
<
nelem
(
selfree
))
{
sel
=
selfree
[
size
];
if
(
sel
!=
nil
)
selfree
[
size
]
=
sel
->
link
;
}
unlock
(
&
chanlock
);
if
(
sel
==
nil
)
sel
=
mal
(
sizeof
(
*
sel
)
+
n
*
sizeof
(
sel
->
scase
[
0
]));
...
...
@@ -517,6 +517,8 @@ sys·selectgo(Select *sel)
p
%=
sel
->
ncase
;
o
%=
sel
->
ncase
;
lock
(
&
chanlock
);
// pass 1 - look for something already waiting
for
(
i
=
0
;
i
<
sel
->
ncase
;
i
++
)
{
cas
=
&
sel
->
scase
[
o
];
...
...
@@ -598,8 +600,10 @@ sys·selectgo(Select *sel)
// (rsc) not correct to set Gwaiting after queueing;
// might already have been readied.
g
->
status
=
Gwaiting
;
unlock
(
&
chanlock
);
sys
·
gosched
();
lock
(
&
chanlock
);
sg
=
g
->
param
;
o
=
sg
->
offset
;
cas
=
&
sel
->
scase
[
o
];
...
...
@@ -629,6 +633,7 @@ sys·selectgo(Select *sel)
asynr
:
asyns
:
unlock
(
&
chanlock
);
throw
(
"asyn"
);
return
;
// compiler doesn't know throw doesn't return
...
...
@@ -671,6 +676,7 @@ retc:
sel
->
link
=
selfree
[
sel
->
ncase
];
selfree
[
sel
->
ncase
]
=
sel
;
}
unlock
(
&
chanlock
);
sys
·
setcallerpc
(
&
sel
,
cas
->
pc
);
as
=
(
byte
*
)
&
sel
+
cas
->
so
;
...
...
src/runtime/proc.c
View file @
376898ca
...
...
@@ -341,8 +341,6 @@ scheduler(void)
{
G
*
gp
;
// Initialization.
m
->
procid
=
getprocid
();
lock
(
&
sched
);
if
(
gosave
(
&
m
->
sched
)){
...
...
@@ -472,7 +470,7 @@ oldstack(void)
mcpy
(
top
->
oldsp
+
16
,
sp
,
siz2
);
}
// call no more functions after this point -
limit register disagrees with R15
// call no more functions after this point -
stackguard disagrees with SP
m
->
curg
->
stackbase
=
top
->
oldbase
;
m
->
curg
->
stackguard
=
top
->
oldguard
;
m
->
morestack
.
SP
=
top
->
oldsp
+
8
;
...
...
src/runtime/rt0_amd64.s
View file @
376898ca
...
...
@@ -33,6 +33,7 @@ TEXT _rt0_amd64(SB),7,$-8
MOVQ 24(SP), AX // copy argv
MOVQ AX, 8(SP)
CALL args(SB)
CALL osinit(SB)
CALL schedinit(SB)
CALL main·init_function(SB) // initialization
...
...
src/runtime/rt1_amd64_darwin.c
View file @
376898ca
This diff is collapsed.
Click to expand it.
src/runtime/rt1_amd64_linux.c
View file @
376898ca
...
...
@@ -427,3 +427,7 @@ sys·sleep(int64 ms)
select
(
0
,
nil
,
nil
,
nil
,
&
tv
);
}
void
osinit
(
void
)
{
}
src/runtime/runtime.h
View file @
376898ca
...
...
@@ -44,7 +44,7 @@ typedef struct M M;
typedef
struct
Stktop
Stktop
;
typedef
struct
Alg
Alg
;
typedef
struct
Lock
Lock
;
typedef
struct
Note
Note
;
typedef
union
Note
Note
;
typedef
struct
Mem
Mem
;
/*
...
...
@@ -78,10 +78,17 @@ enum
struct
Lock
{
uint32
key
;
uint32
sema
;
// for OS X
};
struct
Note
union
Note
{
Lock
lock
;
struct
{
// Linux
Lock
lock
;
};
struct
{
// OS X
int32
wakeup
;
uint32
sema
;
};
};
struct
String
{
...
...
@@ -149,6 +156,7 @@ struct M
G
*
g0
;
// g0 w interrupt stack - must not move
uint64
morearg
;
// arg to morestack - must not move
uint64
cret
;
// return value from C - must not move
uint64
procid
;
// for debuggers - must not move
G
*
curg
;
// current running goroutine
G
*
lastg
;
// last running goroutine - to emulate fifo
Gobuf
sched
;
...
...
@@ -159,8 +167,8 @@ struct M
Note
havenextg
;
G
*
nextg
;
M
*
schedlink
;
int32
procid
;
// for debuggers
Mem
mem
;
uint32
machport
;
// Return address for Mach IPC (OS X)
};
struct
Stktop
{
...
...
@@ -239,7 +247,6 @@ void ready(G*);
byte
*
getenv
(
int8
*
);
int32
atoi
(
byte
*
);
void
newosproc
(
M
*
m
,
G
*
g
,
void
*
stk
,
void
(
*
fn
)(
void
));
int32
getprocid
(
void
);
/*
* mutual exclusion locks. in the uncontended case,
...
...
src/runtime/sys_amd64_darwin.s
View file @
376898ca
...
...
@@ -4,12 +4,11 @@
//
// System calls and other sys.stuff for AMD64, Darwin
// See http://fxr.watson.org/fxr/source/bsd/kern/syscalls.c?v=xnu-1228
// or /usr/include/sys/syscall.h (on a Mac) for system call numbers.
//
// TODO(rsc): Either sys·exit or exit1 is wrong!
// It looks like sys·exit is correct (exits the entire program)
// and exit1 should be mimicking the OS X library routine
// __bsdthread_terminate.
// Exit the entire program (like C exit)
TEXT sys·exit(SB),7,$-8
MOVL 8(SP), DI // arg 1 exit status
MOVL $(0x2000000+1), AX // syscall entry
...
...
@@ -17,9 +16,11 @@ TEXT sys·exit(SB),7,$-8
CALL notok(SB)
RET
// Exit this OS thread (like pthread_exit, which eventually
// calls __bsdthread_terminate).
TEXT exit1(SB),7,$-8
MOVL 8(SP), DI // arg 1 exit status
MOVL $(0x2000000+1), AX // syscall entry
MOVL $(0x2000000+
36
1), AX // syscall entry
SYSCALL
CALL notok(SB)
RET
...
...
@@ -130,3 +131,127 @@ TEXT sys·setcallerpc+0(SB),7,$0
MOVQ x+8(FP), BX
MOVQ BX, -8(AX) // set calling pc
RET
// void bsdthread_create(void *stk, M *m, G *g, void (*fn)(void))
TEXT bsdthread_create(SB),7,$-8
// Set up arguments to bsdthread_create system call.
// The ones in quotes pass through to the thread callback
// uninterpreted, so we can put whatever we want there.
MOVQ fn+32(SP), DI // "func"
MOVQ m+16(SP), SI // "arg"
MOVQ stk+8(SP), DX // stack
MOVQ g+24(SP), R10 // "pthread"
MOVQ $0, R10 // flags
MOVQ $(0x2000000+360), AX // bsdthread_create
SYSCALL
JCC 2(PC)
CALL notok(SB)
RET
// The thread that bsdthread_create creates starts executing here,
// because we registered this function using bsdthread_register
// at startup.
// DI = "pthread" (= g)
// SI = mach thread port
// DX = "func" (= fn)
// CX = "arg" (= m)
// R8 = stack
// R9 = flags (= 0)
// SP = stack - C_64_REDZONE_LEN (= stack - 128)
TEXT bsdthread_start(SB),7,$-8
MOVQ CX, R14 // m
MOVQ DI, R15 // g
MOVQ SI, 24(R14) // thread port is m->procid
CALL DX // fn
CALL exit1(SB)
RET
// void bsdthread_register(void)
// registers callbacks for threadstart (see bsdthread_create above
// and wqthread and pthsize (not used). returns 0 on success.
TEXT bsdthread_register(SB),7,$-8
MOVQ $bsdthread_start(SB), DI // threadstart
MOVQ $0, SI // wqthread, not used by us
MOVQ $0, DX // pthsize, not used by us
MOVQ $(0x2000000+366), AX // bsdthread_register
SYSCALL
JCC 2(PC)
CALL notok(SB)
RET
// int64 select(int32, void*, void*, void*, void*)
TEXT select(SB),7,$0
MOVL 8(SP), DI
MOVQ 16(SP), SI
MOVQ 24(SP), DX
MOVQ 32(SP), R10
MOVQ 40(SP), R8
MOVL $(0x2000000+407), AX // select_nocancel
SYSCALL
RET
// Mach system calls use 0x1000000 instead of the BSD's 0x2000000.
// uint32 mach_msg_trap(void*, uint32, uint32, uint32, uint32, uint32, uint32)
TEXT mach_msg_trap(SB),7,$0
MOVQ 8(SP), DI
MOVL 16(SP), SI
MOVL 20(SP), DX
MOVL 24(SP), R10
MOVL 28(SP), R8
MOVL 32(SP), R9
MOVL 36(SP), R11
PUSHQ R11 // seventh arg, on stack
MOVL $(0x1000000+31), AX // mach_msg_trap
SYSCALL
POPQ R11
RET
TEXT mach_task_self(SB),7,$0
MOVL $(0x1000000+28), AX // task_self_trap
SYSCALL
RET
TEXT mach_thread_self(SB),7,$0
MOVL $(0x1000000+27), AX // thread_self_trap
SYSCALL
RET
TEXT mach_reply_port(SB),7,$0
MOVL $(0x1000000+26), AX // mach_reply_port
SYSCALL
RET
// Mach provides trap versions of the semaphore ops,
// instead of requiring the use of RPC.
// uint32 mach_semaphore_wait(uint32)
TEXT mach_semaphore_wait(SB),7,$0
MOVL 8(SP), DI
MOVL $(0x1000000+36), AX // semaphore_wait_trap
SYSCALL
RET
// uint32 mach_semaphore_timedwait(uint32, uint32, uint32)
TEXT mach_semaphore_timedwait(SB),7,$0
MOVL 8(SP), DI
MOVL 12(SP), SI
MOVL 16(SP), DX
MOVL $(0x1000000+38), AX // semaphore_timedwait_trap
SYSCALL
RET
// uint32 mach_semaphore_signal(uint32)
TEXT mach_semaphore_signal(SB),7,$0
MOVL 8(SP), DI
MOVL $(0x1000000+33), AX // semaphore_signal_trap
SYSCALL
RET
// uint32 mach_semaphore_signal_all(uint32)
TEXT mach_semaphore_signal_all(SB),7,$0
MOVL 8(SP), DI
MOVL $(0x1000000+34), AX // semaphore_signal_all_trap
SYSCALL
RET
src/runtime/sys_amd64_linux.s
View file @
376898ca
...
...
@@ -162,10 +162,17 @@ TEXT clone(SB),7,$0
JEQ 2(PC)
RET
// In child,
call fn on
new stack
// In child,
set up
new stack
MOVQ SI, SP
MOVQ R8, R14 // m
MOVQ R9, R15 // g
// Initialize m->procid to Linux tid
MOVL $186, AX // gettid
SYSCALL
MOVQ AX, 24(R14)
// Call fn
CALL R12
// It shouldn't return. If it does, exi
...
...
@@ -174,7 +181,7 @@ TEXT clone(SB),7,$0
SYSCALL
JMP -3(PC) // keep exiting
// int64 select(int32, void*, void*, void*,
void
*)
// int64 select(int32, void*, void*, void*,
struct timeval
*)
TEXT select(SB),7,$0
MOVL 8(SP), DI
MOVQ 16(SP), SI
...
...
@@ -185,16 +192,3 @@ TEXT select(SB),7,$0
SYSCALL
RET
// Linux allocates each thread its own pid, like Plan 9.
// But the getpid() system call returns the pid of the
// original thread (the one that exec started with),
// no matter which thread asks. This system call,
// which Linux calls gettid, returns the actual pid of
// the calling thread, not the fake one.
//
// int32 getprocid(void)
TEXT getprocid(SB),7,$0
MOVL $186, AX
SYSCALL
RET
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment