select
R=r
APPROVED=r
DELTA=638 (433 added, 21 deleted, 184 changed)
OCL=13426
CL=13438
diff --git a/src/cmd/6g/gen.c b/src/cmd/6g/gen.c
index 3bab742..dfc343d 100644
--- a/src/cmd/6g/gen.c
+++ b/src/cmd/6g/gen.c
@@ -255,6 +255,17 @@
breakpc = sbreak;
break;
+ case OSELECT:
+ gen(n->ninit);
+ sbreak = breakpc;
+ p1 = gbranch(AJMP, T); // goto test
+ breakpc = gbranch(AJMP, T); // break: goto done
+ patch(p1, pc); // test:
+ gen(n->nbody); // select() body
+ patch(breakpc, pc); // done:
+ breakpc = sbreak;
+ break;
+
case OASOP:
cgen_asop(n);
break;
diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h
index c6ee3ab..9b35228 100644
--- a/src/cmd/6g/gg.h
+++ b/src/cmd/6g/gg.h
@@ -107,6 +107,7 @@
void proglist(void);
void gen(Node*);
void swgen(Node*);
+void selgen(Node*);
Node* lookdot(Node*, Node*, int);
void inarggen(void);
void agen_inter(Node*, Node*);
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 9a49f6f..9e37c79 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -219,8 +219,8 @@
OLIST, OCMP,
OPTR, OARRAY,
ORETURN, OFOR, OIF, OSWITCH, OI2S, OS2I, OI2I,
- OAS, OASOP, OCASE, OXCASE, OFALL, OXFALL, OSELECT,
- OGOTO, OPROC, ONEW, OPANIC, OPRINT, OEMPTY,
+ OAS, OASOP, OCASE, OXCASE, OSCASE, OFALL, OXFALL,
+ OGOTO, OPROC, ONEW, OPANIC, OPRINT, OEMPTY, OSELECT,
OOROR,
OANDAND,
@@ -575,6 +575,7 @@
void walkbool(Node*);
Type* walkswitch(Node*, Type*(*)(Node*, Type*));
int casebody(Node*);
+void walkselect(Node*);
int whatis(Node*);
void walkdot(Node*, int);
Node* ascompatee(int, Node**, Node**);
@@ -585,7 +586,9 @@
Node* nodpanic(long);
Node* newcompat(Node*);
Node* stringop(Node*, int);
+Type* fixmap(Type*);
Node* mapop(Node*, int);
+Type* fixchan(Type*);
Node* chanop(Node*, int);
Node* convas(Node*);
void arrayconv(Type*, Node*);
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 13c08ba..769c953 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -338,8 +338,6 @@
| LSWITCH if_stmt
{
popdcl();
- if(!casebody($2->nbody))
- yyerror("switch statement must have case labels");
$$ = $2;
$$->op = OSWITCH;
//if($$->ninit != N && $$->ntest == N)
diff --git a/src/cmd/gc/mksys.bash b/src/cmd/gc/mksys.bash
index 7d6a8ec..c920cde 100755
--- a/src/cmd/gc/mksys.bash
+++ b/src/cmd/gc/mksys.bash
@@ -7,6 +7,7 @@
6g sys.go
echo '1,/((/d
/))/+1,$d
+g/init_.*_function/d
1,$s/foop/sys/g
1,$s/^[ ]*/ "/g
1,$s/$/\\n"/g
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index b9c0da5..8609f39 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -603,6 +603,7 @@
[OCALLINTER] = "CALLINTER",
[OCASE] = "CASE",
[OXCASE] = "XCASE",
+ [OSCASE] = "SCASE",
[OCMP] = "CMP",
[OFALL] = "FALL",
[OCONV] = "CONV",
diff --git a/src/cmd/gc/sys.go b/src/cmd/gc/sys.go
index 06848c1..502d449 100644
--- a/src/cmd/gc/sys.go
+++ b/src/cmd/gc/sys.go
@@ -51,6 +51,11 @@
func chansend1(hchan *chan any, elem any);
func chansend2(hchan *chan any, elem any) (pres bool);
+func newselect(size uint32) (sel *byte);
+func selectsend(sel *byte, hchan *chan any, elem any) (selected bool);
+func selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
+func selectgo(sel *byte);
+
func gosched();
func goexit();
@@ -112,6 +117,12 @@
chansend1
chansend2
+ // select
+ newselect
+ selectsend
+ selectrecv
+ selectgo
+
// go routines
gosched
goexit
diff --git a/src/cmd/gc/sysimport.c b/src/cmd/gc/sysimport.c
index b596408..571c7e8 100644
--- a/src/cmd/gc/sysimport.c
+++ b/src/cmd/gc/sysimport.c
@@ -3,10 +3,10 @@
"type sys._esys_002 {}\n"
"type sys.any 24\n"
"type sys._esys_003 *sys.any\n"
- "type sys._osys_332 {_esys_330 sys._esys_003}\n"
+ "type sys._osys_361 {_esys_359 sys._esys_003}\n"
"type sys.uint32 6\n"
- "type sys._isys_334 {_esys_331 sys.uint32}\n"
- "type sys._esys_001 (sys._esys_002 sys._osys_332 sys._isys_334)\n"
+ "type sys._isys_363 {_esys_360 sys.uint32}\n"
+ "type sys._esys_001 (sys._esys_002 sys._osys_361 sys._isys_363)\n"
"var !sys.mal sys._esys_001\n"
"type sys._esys_005 {}\n"
"type sys._esys_006 {}\n"
@@ -16,249 +16,282 @@
"type sys._esys_009 {}\n"
"type sys._esys_010 {}\n"
"type sys.int32 5\n"
- "type sys._isys_340 {_esys_339 sys.int32}\n"
- "type sys._esys_008 (sys._esys_009 sys._esys_010 sys._isys_340)\n"
+ "type sys._isys_369 {_esys_368 sys.int32}\n"
+ "type sys._esys_008 (sys._esys_009 sys._esys_010 sys._isys_369)\n"
"var !sys.panicl sys._esys_008\n"
"type sys._esys_012 {}\n"
"type sys._esys_013 {}\n"
"type sys.bool 12\n"
- "type sys._isys_345 {_esys_344 sys.bool}\n"
- "type sys._esys_011 (sys._esys_012 sys._esys_013 sys._isys_345)\n"
+ "type sys._isys_374 {_esys_373 sys.bool}\n"
+ "type sys._esys_011 (sys._esys_012 sys._esys_013 sys._isys_374)\n"
"var !sys.printbool sys._esys_011\n"
"type sys._esys_015 {}\n"
"type sys._esys_016 {}\n"
"type sys.float64 10\n"
- "type sys._isys_350 {_esys_349 sys.float64}\n"
- "type sys._esys_014 (sys._esys_015 sys._esys_016 sys._isys_350)\n"
+ "type sys._isys_379 {_esys_378 sys.float64}\n"
+ "type sys._esys_014 (sys._esys_015 sys._esys_016 sys._isys_379)\n"
"var !sys.printfloat sys._esys_014\n"
"type sys._esys_018 {}\n"
"type sys._esys_019 {}\n"
"type sys.int64 7\n"
- "type sys._isys_355 {_esys_354 sys.int64}\n"
- "type sys._esys_017 (sys._esys_018 sys._esys_019 sys._isys_355)\n"
+ "type sys._isys_384 {_esys_383 sys.int64}\n"
+ "type sys._esys_017 (sys._esys_018 sys._esys_019 sys._isys_384)\n"
"var !sys.printint sys._esys_017\n"
"type sys._esys_021 {}\n"
"type sys._esys_022 {}\n"
"type sys._esys_023 25\n"
"type sys.string *sys._esys_023\n"
- "type sys._isys_360 {_esys_359 sys.string}\n"
- "type sys._esys_020 (sys._esys_021 sys._esys_022 sys._isys_360)\n"
+ "type sys._isys_389 {_esys_388 sys.string}\n"
+ "type sys._esys_020 (sys._esys_021 sys._esys_022 sys._isys_389)\n"
"var !sys.printstring sys._esys_020\n"
"type sys._esys_025 {}\n"
"type sys._esys_026 {}\n"
"type sys._esys_027 *sys.any\n"
- "type sys._isys_365 {_esys_364 sys._esys_027}\n"
- "type sys._esys_024 (sys._esys_025 sys._esys_026 sys._isys_365)\n"
+ "type sys._isys_394 {_esys_393 sys._esys_027}\n"
+ "type sys._esys_024 (sys._esys_025 sys._esys_026 sys._isys_394)\n"
"var !sys.printpointer sys._esys_024\n"
"type sys._esys_029 {}\n"
- "type sys._osys_372 {_esys_369 sys.string}\n"
- "type sys._isys_374 {_esys_370 sys.string _esys_371 sys.string}\n"
- "type sys._esys_028 (sys._esys_029 sys._osys_372 sys._isys_374)\n"
+ "type sys._osys_401 {_esys_398 sys.string}\n"
+ "type sys._isys_403 {_esys_399 sys.string _esys_400 sys.string}\n"
+ "type sys._esys_028 (sys._esys_029 sys._osys_401 sys._isys_403)\n"
"var !sys.catstring sys._esys_028\n"
"type sys._esys_031 {}\n"
- "type sys._osys_382 {_esys_379 sys.int32}\n"
- "type sys._isys_384 {_esys_380 sys.string _esys_381 sys.string}\n"
- "type sys._esys_030 (sys._esys_031 sys._osys_382 sys._isys_384)\n"
+ "type sys._osys_411 {_esys_408 sys.int32}\n"
+ "type sys._isys_413 {_esys_409 sys.string _esys_410 sys.string}\n"
+ "type sys._esys_030 (sys._esys_031 sys._osys_411 sys._isys_413)\n"
"var !sys.cmpstring sys._esys_030\n"
"type sys._esys_033 {}\n"
- "type sys._osys_393 {_esys_389 sys.string}\n"
- "type sys._isys_395 {_esys_390 sys.string _esys_391 sys.int32 _esys_392 sys.int32}\n"
- "type sys._esys_032 (sys._esys_033 sys._osys_393 sys._isys_395)\n"
+ "type sys._osys_422 {_esys_418 sys.string}\n"
+ "type sys._isys_424 {_esys_419 sys.string _esys_420 sys.int32 _esys_421 sys.int32}\n"
+ "type sys._esys_032 (sys._esys_033 sys._osys_422 sys._isys_424)\n"
"var !sys.slicestring sys._esys_032\n"
"type sys._esys_035 {}\n"
"type sys.uint8 2\n"
- "type sys._osys_404 {_esys_401 sys.uint8}\n"
- "type sys._isys_406 {_esys_402 sys.string _esys_403 sys.int32}\n"
- "type sys._esys_034 (sys._esys_035 sys._osys_404 sys._isys_406)\n"
+ "type sys._osys_433 {_esys_430 sys.uint8}\n"
+ "type sys._isys_435 {_esys_431 sys.string _esys_432 sys.int32}\n"
+ "type sys._esys_034 (sys._esys_035 sys._osys_433 sys._isys_435)\n"
"var !sys.indexstring sys._esys_034\n"
"type sys._esys_037 {}\n"
- "type sys._osys_413 {_esys_411 sys.string}\n"
- "type sys._isys_415 {_esys_412 sys.int64}\n"
- "type sys._esys_036 (sys._esys_037 sys._osys_413 sys._isys_415)\n"
+ "type sys._osys_442 {_esys_440 sys.string}\n"
+ "type sys._isys_444 {_esys_441 sys.int64}\n"
+ "type sys._esys_036 (sys._esys_037 sys._osys_442 sys._isys_444)\n"
"var !sys.intstring sys._esys_036\n"
"type sys._esys_039 {}\n"
- "type sys._osys_422 {_esys_419 sys.string}\n"
+ "type sys._osys_451 {_esys_448 sys.string}\n"
"type sys._esys_040 *sys.uint8\n"
- "type sys._isys_424 {_esys_420 sys._esys_040 _esys_421 sys.int32}\n"
- "type sys._esys_038 (sys._esys_039 sys._osys_422 sys._isys_424)\n"
+ "type sys._isys_453 {_esys_449 sys._esys_040 _esys_450 sys.int32}\n"
+ "type sys._esys_038 (sys._esys_039 sys._osys_451 sys._isys_453)\n"
"var !sys.byteastring sys._esys_038\n"
"type sys._esys_042 {}\n"
"type sys._esys_043 <>\n"
- "type sys._osys_433 {_esys_429 sys._esys_043}\n"
+ "type sys._osys_462 {_esys_458 sys._esys_043}\n"
"type sys._esys_044 *sys.uint8\n"
"type sys._esys_045 *sys.uint8\n"
- "type sys._ssys_440 {}\n"
- "type sys._esys_046 *sys._ssys_440\n"
- "type sys._isys_435 {_esys_430 sys._esys_044 _esys_431 sys._esys_045 _esys_432 sys._esys_046}\n"
- "type sys._esys_041 (sys._esys_042 sys._osys_433 sys._isys_435)\n"
+ "type sys._ssys_469 {}\n"
+ "type sys._esys_046 *sys._ssys_469\n"
+ "type sys._isys_464 {_esys_459 sys._esys_044 _esys_460 sys._esys_045 _esys_461 sys._esys_046}\n"
+ "type sys._esys_041 (sys._esys_042 sys._osys_462 sys._isys_464)\n"
"var !sys.mkiface sys._esys_041\n"
"type sys._esys_048 {}\n"
- "type sys._osys_444 {_esys_443 sys.int32}\n"
+ "type sys._osys_473 {_esys_472 sys.int32}\n"
"type sys._esys_049 {}\n"
- "type sys._esys_047 (sys._esys_048 sys._osys_444 sys._esys_049)\n"
+ "type sys._esys_047 (sys._esys_048 sys._osys_473 sys._esys_049)\n"
"var !sys.argc sys._esys_047\n"
"type sys._esys_051 {}\n"
- "type sys._osys_448 {_esys_447 sys.int32}\n"
+ "type sys._osys_477 {_esys_476 sys.int32}\n"
"type sys._esys_052 {}\n"
- "type sys._esys_050 (sys._esys_051 sys._osys_448 sys._esys_052)\n"
+ "type sys._esys_050 (sys._esys_051 sys._osys_477 sys._esys_052)\n"
"var !sys.envc sys._esys_050\n"
"type sys._esys_054 {}\n"
- "type sys._osys_453 {_esys_451 sys.string}\n"
- "type sys._isys_455 {_esys_452 sys.int32}\n"
- "type sys._esys_053 (sys._esys_054 sys._osys_453 sys._isys_455)\n"
+ "type sys._osys_482 {_esys_480 sys.string}\n"
+ "type sys._isys_484 {_esys_481 sys.int32}\n"
+ "type sys._esys_053 (sys._esys_054 sys._osys_482 sys._isys_484)\n"
"var !sys.argv sys._esys_053\n"
"type sys._esys_056 {}\n"
- "type sys._osys_461 {_esys_459 sys.string}\n"
- "type sys._isys_463 {_esys_460 sys.int32}\n"
- "type sys._esys_055 (sys._esys_056 sys._osys_461 sys._isys_463)\n"
+ "type sys._osys_490 {_esys_488 sys.string}\n"
+ "type sys._isys_492 {_esys_489 sys.int32}\n"
+ "type sys._esys_055 (sys._esys_056 sys._osys_490 sys._isys_492)\n"
"var !sys.envv sys._esys_055\n"
"type sys._esys_058 {}\n"
- "type sys._osys_470 {_esys_467 sys.float64 _esys_468 sys.int32}\n"
- "type sys._isys_472 {_esys_469 sys.float64}\n"
- "type sys._esys_057 (sys._esys_058 sys._osys_470 sys._isys_472)\n"
+ "type sys._osys_499 {_esys_496 sys.float64 _esys_497 sys.int32}\n"
+ "type sys._isys_501 {_esys_498 sys.float64}\n"
+ "type sys._esys_057 (sys._esys_058 sys._osys_499 sys._isys_501)\n"
"var !sys.frexp sys._esys_057\n"
"type sys._esys_060 {}\n"
- "type sys._osys_479 {_esys_476 sys.float64}\n"
- "type sys._isys_481 {_esys_477 sys.float64 _esys_478 sys.int32}\n"
- "type sys._esys_059 (sys._esys_060 sys._osys_479 sys._isys_481)\n"
+ "type sys._osys_508 {_esys_505 sys.float64}\n"
+ "type sys._isys_510 {_esys_506 sys.float64 _esys_507 sys.int32}\n"
+ "type sys._esys_059 (sys._esys_060 sys._osys_508 sys._isys_510)\n"
"var !sys.ldexp sys._esys_059\n"
"type sys._esys_062 {}\n"
- "type sys._osys_489 {_esys_486 sys.float64 _esys_487 sys.float64}\n"
- "type sys._isys_491 {_esys_488 sys.float64}\n"
- "type sys._esys_061 (sys._esys_062 sys._osys_489 sys._isys_491)\n"
+ "type sys._osys_518 {_esys_515 sys.float64 _esys_516 sys.float64}\n"
+ "type sys._isys_520 {_esys_517 sys.float64}\n"
+ "type sys._esys_061 (sys._esys_062 sys._osys_518 sys._isys_520)\n"
"var !sys.modf sys._esys_061\n"
"type sys._esys_064 {}\n"
- "type sys._osys_498 {_esys_495 sys.bool}\n"
- "type sys._isys_500 {_esys_496 sys.float64 _esys_497 sys.int32}\n"
- "type sys._esys_063 (sys._esys_064 sys._osys_498 sys._isys_500)\n"
+ "type sys._osys_527 {_esys_524 sys.bool}\n"
+ "type sys._isys_529 {_esys_525 sys.float64 _esys_526 sys.int32}\n"
+ "type sys._esys_063 (sys._esys_064 sys._osys_527 sys._isys_529)\n"
"var !sys.isInf sys._esys_063\n"
"type sys._esys_066 {}\n"
- "type sys._osys_507 {_esys_505 sys.bool}\n"
- "type sys._isys_509 {_esys_506 sys.float64}\n"
- "type sys._esys_065 (sys._esys_066 sys._osys_507 sys._isys_509)\n"
+ "type sys._osys_536 {_esys_534 sys.bool}\n"
+ "type sys._isys_538 {_esys_535 sys.float64}\n"
+ "type sys._esys_065 (sys._esys_066 sys._osys_536 sys._isys_538)\n"
"var !sys.isNaN sys._esys_065\n"
"type sys._esys_068 {}\n"
- "type sys._osys_515 {_esys_513 sys.float64}\n"
- "type sys._isys_517 {_esys_514 sys.int32}\n"
- "type sys._esys_067 (sys._esys_068 sys._osys_515 sys._isys_517)\n"
+ "type sys._osys_544 {_esys_542 sys.float64}\n"
+ "type sys._isys_546 {_esys_543 sys.int32}\n"
+ "type sys._esys_067 (sys._esys_068 sys._osys_544 sys._isys_546)\n"
"var !sys.Inf sys._esys_067\n"
"type sys._esys_070 {}\n"
- "type sys._osys_522 {_esys_521 sys.float64}\n"
+ "type sys._osys_551 {_esys_550 sys.float64}\n"
"type sys._esys_071 {}\n"
- "type sys._esys_069 (sys._esys_070 sys._osys_522 sys._esys_071)\n"
+ "type sys._esys_069 (sys._esys_070 sys._osys_551 sys._esys_071)\n"
"var !sys.NaN sys._esys_069\n"
"type sys._esys_073 {}\n"
"type sys._esys_075 [sys.any] sys.any\n"
"type sys._esys_074 *sys._esys_075\n"
- "type sys._osys_525 {hmap sys._esys_074}\n"
- "type sys._isys_527 {keysize sys.uint32 valsize sys.uint32 keyalg sys.uint32 valalg sys.uint32 hint sys.uint32}\n"
- "type sys._esys_072 (sys._esys_073 sys._osys_525 sys._isys_527)\n"
+ "type sys._osys_554 {hmap sys._esys_074}\n"
+ "type sys._isys_556 {keysize sys.uint32 valsize sys.uint32 keyalg sys.uint32 valalg sys.uint32 hint sys.uint32}\n"
+ "type sys._esys_072 (sys._esys_073 sys._osys_554 sys._isys_556)\n"
"var !sys.newmap sys._esys_072\n"
"type sys._esys_077 {}\n"
- "type sys._osys_536 {val sys.any}\n"
+ "type sys._osys_565 {val sys.any}\n"
"type sys._esys_079 [sys.any] sys.any\n"
"type sys._esys_078 *sys._esys_079\n"
- "type sys._isys_538 {hmap sys._esys_078 key sys.any}\n"
- "type sys._esys_076 (sys._esys_077 sys._osys_536 sys._isys_538)\n"
+ "type sys._isys_567 {hmap sys._esys_078 key sys.any}\n"
+ "type sys._esys_076 (sys._esys_077 sys._osys_565 sys._isys_567)\n"
"var !sys.mapaccess1 sys._esys_076\n"
"type sys._esys_081 {}\n"
- "type sys._osys_544 {val sys.any pres sys.bool}\n"
+ "type sys._osys_573 {val sys.any pres sys.bool}\n"
"type sys._esys_083 [sys.any] sys.any\n"
"type sys._esys_082 *sys._esys_083\n"
- "type sys._isys_546 {hmap sys._esys_082 key sys.any}\n"
- "type sys._esys_080 (sys._esys_081 sys._osys_544 sys._isys_546)\n"
+ "type sys._isys_575 {hmap sys._esys_082 key sys.any}\n"
+ "type sys._esys_080 (sys._esys_081 sys._osys_573 sys._isys_575)\n"
"var !sys.mapaccess2 sys._esys_080\n"
"type sys._esys_085 {}\n"
"type sys._esys_086 {}\n"
"type sys._esys_088 [sys.any] sys.any\n"
"type sys._esys_087 *sys._esys_088\n"
- "type sys._isys_553 {hmap sys._esys_087 key sys.any val sys.any}\n"
- "type sys._esys_084 (sys._esys_085 sys._esys_086 sys._isys_553)\n"
+ "type sys._isys_582 {hmap sys._esys_087 key sys.any val sys.any}\n"
+ "type sys._esys_084 (sys._esys_085 sys._esys_086 sys._isys_582)\n"
"var !sys.mapassign1 sys._esys_084\n"
"type sys._esys_090 {}\n"
"type sys._esys_091 {}\n"
"type sys._esys_093 [sys.any] sys.any\n"
"type sys._esys_092 *sys._esys_093\n"
- "type sys._isys_559 {hmap sys._esys_092 key sys.any val sys.any pres sys.bool}\n"
- "type sys._esys_089 (sys._esys_090 sys._esys_091 sys._isys_559)\n"
+ "type sys._isys_588 {hmap sys._esys_092 key sys.any val sys.any pres sys.bool}\n"
+ "type sys._esys_089 (sys._esys_090 sys._esys_091 sys._isys_588)\n"
"var !sys.mapassign2 sys._esys_089\n"
"type sys._esys_095 {}\n"
"type sys._esys_097 1 sys.any\n"
"type sys._esys_096 *sys._esys_097\n"
- "type sys._osys_566 {hchan sys._esys_096}\n"
- "type sys._isys_568 {elemsize sys.uint32 elemalg sys.uint32 hint sys.uint32}\n"
- "type sys._esys_094 (sys._esys_095 sys._osys_566 sys._isys_568)\n"
+ "type sys._osys_595 {hchan sys._esys_096}\n"
+ "type sys._isys_597 {elemsize sys.uint32 elemalg sys.uint32 hint sys.uint32}\n"
+ "type sys._esys_094 (sys._esys_095 sys._osys_595 sys._isys_597)\n"
"var !sys.newchan sys._esys_094\n"
"type sys._esys_099 {}\n"
- "type sys._osys_575 {elem sys.any}\n"
+ "type sys._osys_604 {elem sys.any}\n"
"type sys._esys_101 1 sys.any\n"
"type sys._esys_100 *sys._esys_101\n"
- "type sys._isys_577 {hchan sys._esys_100}\n"
- "type sys._esys_098 (sys._esys_099 sys._osys_575 sys._isys_577)\n"
+ "type sys._isys_606 {hchan sys._esys_100}\n"
+ "type sys._esys_098 (sys._esys_099 sys._osys_604 sys._isys_606)\n"
"var !sys.chanrecv1 sys._esys_098\n"
"type sys._esys_103 {}\n"
- "type sys._osys_582 {elem sys.any pres sys.bool}\n"
+ "type sys._osys_611 {elem sys.any pres sys.bool}\n"
"type sys._esys_105 1 sys.any\n"
"type sys._esys_104 *sys._esys_105\n"
- "type sys._isys_584 {hchan sys._esys_104}\n"
- "type sys._esys_102 (sys._esys_103 sys._osys_582 sys._isys_584)\n"
+ "type sys._isys_613 {hchan sys._esys_104}\n"
+ "type sys._esys_102 (sys._esys_103 sys._osys_611 sys._isys_613)\n"
"var !sys.chanrecv2 sys._esys_102\n"
"type sys._esys_107 {}\n"
- "type sys._osys_590 {elem sys.any pres sys.bool}\n"
+ "type sys._osys_619 {elem sys.any pres sys.bool}\n"
"type sys._esys_109 1 sys.any\n"
"type sys._esys_108 *sys._esys_109\n"
- "type sys._isys_592 {hchan sys._esys_108}\n"
- "type sys._esys_106 (sys._esys_107 sys._osys_590 sys._isys_592)\n"
+ "type sys._isys_621 {hchan sys._esys_108}\n"
+ "type sys._esys_106 (sys._esys_107 sys._osys_619 sys._isys_621)\n"
"var !sys.chanrecv3 sys._esys_106\n"
"type sys._esys_111 {}\n"
"type sys._esys_112 {}\n"
"type sys._esys_114 1 sys.any\n"
"type sys._esys_113 *sys._esys_114\n"
- "type sys._isys_598 {hchan sys._esys_113 elem sys.any}\n"
- "type sys._esys_110 (sys._esys_111 sys._esys_112 sys._isys_598)\n"
+ "type sys._isys_627 {hchan sys._esys_113 elem sys.any}\n"
+ "type sys._esys_110 (sys._esys_111 sys._esys_112 sys._isys_627)\n"
"var !sys.chansend1 sys._esys_110\n"
"type sys._esys_116 {}\n"
- "type sys._osys_603 {pres sys.bool}\n"
+ "type sys._osys_632 {pres sys.bool}\n"
"type sys._esys_118 1 sys.any\n"
"type sys._esys_117 *sys._esys_118\n"
- "type sys._isys_605 {hchan sys._esys_117 elem sys.any}\n"
- "type sys._esys_115 (sys._esys_116 sys._osys_603 sys._isys_605)\n"
+ "type sys._isys_634 {hchan sys._esys_117 elem sys.any}\n"
+ "type sys._esys_115 (sys._esys_116 sys._osys_632 sys._isys_634)\n"
"var !sys.chansend2 sys._esys_115\n"
"type sys._esys_120 {}\n"
- "type sys._esys_121 {}\n"
- "type sys._esys_122 {}\n"
- "type sys._esys_119 (sys._esys_120 sys._esys_121 sys._esys_122)\n"
- "var !sys.gosched sys._esys_119\n"
- "type sys._esys_124 {}\n"
- "type sys._esys_125 {}\n"
- "type sys._esys_126 {}\n"
- "type sys._esys_123 (sys._esys_124 sys._esys_125 sys._esys_126)\n"
- "var !sys.goexit sys._esys_123\n"
+ "type sys._esys_121 *sys.uint8\n"
+ "type sys._osys_640 {sel sys._esys_121}\n"
+ "type sys._isys_642 {size sys.uint32}\n"
+ "type sys._esys_119 (sys._esys_120 sys._osys_640 sys._isys_642)\n"
+ "var !sys.newselect sys._esys_119\n"
+ "type sys._esys_123 {}\n"
+ "type sys._osys_647 {selected sys.bool}\n"
+ "type sys._esys_124 *sys.uint8\n"
+ "type sys._esys_126 1 sys.any\n"
+ "type sys._esys_125 *sys._esys_126\n"
+ "type sys._isys_649 {sel sys._esys_124 hchan sys._esys_125 elem sys.any}\n"
+ "type sys._esys_122 (sys._esys_123 sys._osys_647 sys._isys_649)\n"
+ "var !sys.selectsend sys._esys_122\n"
"type sys._esys_128 {}\n"
- "type sys._osys_616 {_esys_613 sys.string _esys_614 sys.bool}\n"
- "type sys._isys_618 {_esys_615 sys.string}\n"
- "type sys._esys_127 (sys._esys_128 sys._osys_616 sys._isys_618)\n"
- "var !sys.readfile sys._esys_127\n"
- "type sys._esys_130 {}\n"
- "type sys._osys_625 {_esys_622 sys.bool}\n"
- "type sys._isys_627 {_esys_623 sys.string _esys_624 sys.string}\n"
- "type sys._esys_129 (sys._esys_130 sys._osys_625 sys._isys_627)\n"
- "var !sys.writefile sys._esys_129\n"
- "type sys._esys_132 {}\n"
- "type sys._osys_637 {_esys_632 sys.int32 _esys_633 sys.int32}\n"
- "type sys._esys_133 *sys.uint8\n"
- "type sys._isys_639 {_esys_634 sys._esys_133 _esys_635 sys.int32 _esys_636 sys.int32}\n"
- "type sys._esys_131 (sys._esys_132 sys._osys_637 sys._isys_639)\n"
- "var !sys.bytestorune sys._esys_131\n"
+ "type sys._osys_656 {selected sys.bool}\n"
+ "type sys._esys_129 *sys.uint8\n"
+ "type sys._esys_131 1 sys.any\n"
+ "type sys._esys_130 *sys._esys_131\n"
+ "type sys._esys_132 *sys.any\n"
+ "type sys._isys_658 {sel sys._esys_129 hchan sys._esys_130 elem sys._esys_132}\n"
+ "type sys._esys_127 (sys._esys_128 sys._osys_656 sys._isys_658)\n"
+ "var !sys.selectrecv sys._esys_127\n"
+ "type sys._esys_134 {}\n"
"type sys._esys_135 {}\n"
- "type sys._osys_650 {_esys_645 sys.int32 _esys_646 sys.int32}\n"
- "type sys._isys_652 {_esys_647 sys.string _esys_648 sys.int32 _esys_649 sys.int32}\n"
- "type sys._esys_134 (sys._esys_135 sys._osys_650 sys._isys_652)\n"
- "var !sys.stringtorune sys._esys_134\n"
- "type sys._esys_137 {}\n"
+ "type sys._esys_136 *sys.uint8\n"
+ "type sys._isys_665 {sel sys._esys_136}\n"
+ "type sys._esys_133 (sys._esys_134 sys._esys_135 sys._isys_665)\n"
+ "var !sys.selectgo sys._esys_133\n"
"type sys._esys_138 {}\n"
- "type sys._isys_659 {_esys_658 sys.int32}\n"
- "type sys._esys_136 (sys._esys_137 sys._esys_138 sys._isys_659)\n"
- "var !sys.exit sys._esys_136\n"
+ "type sys._esys_139 {}\n"
+ "type sys._esys_140 {}\n"
+ "type sys._esys_137 (sys._esys_138 sys._esys_139 sys._esys_140)\n"
+ "var !sys.gosched sys._esys_137\n"
+ "type sys._esys_142 {}\n"
+ "type sys._esys_143 {}\n"
+ "type sys._esys_144 {}\n"
+ "type sys._esys_141 (sys._esys_142 sys._esys_143 sys._esys_144)\n"
+ "var !sys.goexit sys._esys_141\n"
+ "type sys._esys_146 {}\n"
+ "type sys._osys_674 {_esys_671 sys.string _esys_672 sys.bool}\n"
+ "type sys._isys_676 {_esys_673 sys.string}\n"
+ "type sys._esys_145 (sys._esys_146 sys._osys_674 sys._isys_676)\n"
+ "var !sys.readfile sys._esys_145\n"
+ "type sys._esys_148 {}\n"
+ "type sys._osys_683 {_esys_680 sys.bool}\n"
+ "type sys._isys_685 {_esys_681 sys.string _esys_682 sys.string}\n"
+ "type sys._esys_147 (sys._esys_148 sys._osys_683 sys._isys_685)\n"
+ "var !sys.writefile sys._esys_147\n"
+ "type sys._esys_150 {}\n"
+ "type sys._osys_695 {_esys_690 sys.int32 _esys_691 sys.int32}\n"
+ "type sys._esys_151 *sys.uint8\n"
+ "type sys._isys_697 {_esys_692 sys._esys_151 _esys_693 sys.int32 _esys_694 sys.int32}\n"
+ "type sys._esys_149 (sys._esys_150 sys._osys_695 sys._isys_697)\n"
+ "var !sys.bytestorune sys._esys_149\n"
+ "type sys._esys_153 {}\n"
+ "type sys._osys_708 {_esys_703 sys.int32 _esys_704 sys.int32}\n"
+ "type sys._isys_710 {_esys_705 sys.string _esys_706 sys.int32 _esys_707 sys.int32}\n"
+ "type sys._esys_152 (sys._esys_153 sys._osys_708 sys._isys_710)\n"
+ "var !sys.stringtorune sys._esys_152\n"
+ "type sys._esys_155 {}\n"
+ "type sys._esys_156 {}\n"
+ "type sys._isys_717 {_esys_716 sys.int32}\n"
+ "type sys._esys_154 (sys._esys_155 sys._esys_156 sys._isys_717)\n"
+ "var !sys.exit sys._esys_154\n"
+ "type sys._esys_158 {}\n"
+ "type sys._esys_159 {}\n"
+ "type sys._esys_160 {}\n"
+ "type sys._esys_157 (sys._esys_158 sys._esys_159 sys._esys_160)\n"
"))\n"
;
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 576fe90..422b551 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -70,7 +70,7 @@
if(top != Etop)
goto nottop;
walktype(n->left, Erv);
- *n = *nod(OLIST, prcompat(n->left), nodpanic(n->lineno));
+ *n = *list(prcompat(n->left), nodpanic(n->lineno));
goto ret;
case OLITERAL:
@@ -121,6 +121,9 @@
if(top != Etop)
goto nottop;
+ if(!casebody(n->nbody))
+ yyerror("switch statement must have case labels");
+
if(n->ntest == N)
n->ntest = booltrue;
walktype(n->ninit, Etop);
@@ -142,6 +145,20 @@
walktype(n->nincr, Erv);
goto ret;
+ case OSELECT:
+ if(top != Etop)
+ goto nottop;
+
+ walkselect(n);
+ goto ret;
+
+ case OSCASE:
+ if(top != Etop)
+ goto nottop;
+// walktype(n->left, Erv); SPECIAL
+ n = n->right;
+ goto loop;
+
case OEMPTY:
if(top != Etop)
goto nottop;
@@ -216,7 +233,7 @@
l = ascompatte(n->op, getinarg(t), &n->right, 0);
r = ascompatte(n->op, getthis(t), &n->left->left, 0);
if(l != N)
- r = nod(OLIST, r, l);
+ r = list(r, l);
n->left->left = N;
ullmancalc(n->left);
n->right = reorder1(r);
@@ -255,7 +272,7 @@
walktype(r, Erv);
l = ascompatet(n->op, &n->left, &r->type, 0);
if(l != N) {
- *n = *nod(OLIST, r, reorder2(l));
+ *n = *list(r, reorder2(l));
}
goto ret;
}
@@ -591,8 +608,8 @@
case OSEND:
if(top == Elv)
goto nottop;
- walktype(n->left, Erv);
- walktype(n->right, Erv);
+ walktype(n->left, Erv); // chan
+ walktype(n->right, Erv); // e
*n = *chanop(n, top);
goto ret;
@@ -805,7 +822,7 @@
}
/*
- * check that selected type
+ * check that switch type
* is compat with all the cases
*/
Type*
@@ -897,6 +914,125 @@
goto loop;
}
+Node*
+selcase(Node *c, Node *var)
+{
+ Node *a, *r, *on;
+ Type *t;
+
+ walktype(c->left, Erv); // chan
+ walktype(c->right, Erv); // elem
+ t = fixchan(c->left->type);
+ if(t == T)
+ return;
+
+ convlit(c->right, t->type);
+ if(!ascompat(t->type, c->right->type)) {
+ badtype(c->op, t->type, c->right->type);
+ return;
+ }
+
+ // selectsend(sel *byte, hchan *chan any, elem any) (selected bool);
+ on = syslook("selectsend", 1);
+ argtype(on, t->type);
+ argtype(on, t->type);
+
+ a = c->right; // elem
+ r = a;
+ a = c->left; // chan
+ r = list(a, r);
+ a = var; // sel-var
+ r = list(a, r);
+
+ a = nod(OCALL, on, r);
+ r = nod(OIF, N, N);
+ r->ntest = a;
+
+ return r;
+
+}
+
+void
+walkselect(Node *sel)
+{
+ Iter iter;
+ Node *n, *oc, *on, *r;
+ Node *var, *bod, *res;
+ int count;
+ long lno;
+
+ lno = setlineno(sel);
+
+ // generate sel-struct
+ var = nod(OXXX, N, N);
+ tempname(var, ptrto(types[TUINT8]));
+
+ n = listfirst(&iter, &sel->left);
+ if(n == N || n->op != OXCASE)
+ yyerror("first select statement must be a case");
+
+ count = 0; // number of cases
+ res = N; // entire select body
+ bod = N; // body of each case
+ oc = N; // last case
+
+ for(count=0; n!=N; n=listnext(&iter)) {
+ setlineno(n);
+
+ switch(n->op) {
+ default:
+ bod = list(bod, n);
+ break;
+
+ case OXCASE:
+ switch(n->left->op) {
+ default:
+ yyerror("select cases must be send or recv");
+ break;
+
+ case OSEND:
+ if(oc != N) {
+ bod = list(bod, nod(OBREAK, N, N));
+ oc->nbody = rev(bod);
+ }
+ oc = selcase(n->left, var);
+ res = list(res, oc);
+ break;
+ }
+ bod = N;
+ count++;
+ break;
+ }
+ }
+ if(oc != N) {
+ bod = list(bod, nod(OBREAK, N, N));
+ oc->nbody = rev(bod);
+ }
+ setlineno(sel);
+
+ // selectgo(sel *byte);
+ on = syslook("selectgo", 0);
+ r = nod(OCALL, on, var); // sel-var
+ res = list(res, r);
+
+ // newselect(size uint32) (sel *byte);
+ on = syslook("newselect", 0);
+
+ r = nod(OXXX, N, N);
+ nodconst(r, types[TINT32], count); // count
+ r = nod(OCALL, on, r);
+ r = nod(OAS, var, r);
+
+ sel->ninit = r;
+ sel->nbody = rev(res);
+ sel->left = N;
+
+ walktype(sel->ninit, Etop);
+ walktype(sel->nbody, Etop);
+
+ lineno = lno;
+}
+
/*
* allowable type combinations for
* normal binary operations.
@@ -1053,7 +1189,7 @@
if(nn == N)
nn = a;
else
- nn = nod(OLIST, a, nn);
+ nn = list(a, nn);
l = listnext(&savel);
r = listnext(&saver);
@@ -1093,7 +1229,7 @@
if(nn == N)
nn = a;
else
- nn = nod(OLIST, a, nn);
+ nn = list(a, nn);
l = listnext(&savel);
r = structnext(&saver);
@@ -1134,7 +1270,7 @@
if(nn == N)
nn = a;
else
- nn = nod(OLIST, a, nn);
+ nn = list(a, nn);
l = structnext(&savel);
r = listnext(&saver);
@@ -1230,7 +1366,7 @@
if(r == N)
r = nod(OCALL, on, l);
else
- r = nod(OLIST, r, nod(OCALL, on, l));
+ r = list(r, nod(OCALL, on, l));
l = listnext(&save);
goto loop;
@@ -1305,7 +1441,7 @@
case OLT:
// sys_cmpstring(s1, s2) :: 0
on = syslook("cmpstring", 0);
- r = nod(OLIST, n->left, n->right);
+ r = list(n->left, n->right);
r = nod(OCALL, on, r);
c = nodintconst(0);
r = nod(n->op, r, c);
@@ -1314,7 +1450,7 @@
case OADD:
// sys_catstring(s1, s2)
on = syslook("catstring", 0);
- r = nod(OLIST, n->left, n->right);
+ r = list(n->left, n->right);
r = nod(OCALL, on, r);
break;
@@ -1328,7 +1464,7 @@
// s1 = sys_catstring(s1, s2)
if(n->etype != OADD)
fatal("stringop: not cat");
- r = nod(OLIST, n->left, n->right);
+ r = list(n->left, n->right);
on = syslook("catstring", 0);
r = nod(OCALL, on, r);
r = nod(OAS, n->left, r);
@@ -1344,8 +1480,8 @@
c = nod(OCONV, n->right->right, N);
c->type = types[TINT32];
- r = nod(OLIST, r, c);
- r = nod(OLIST, n->left, r);
+ r = list(r, c);
+ r = list(n->left, r);
on = syslook("slicestring", 0);
r = nod(OCALL, on, r);
break;
@@ -1360,7 +1496,7 @@
}
r = nod(OCONV, n->right, N);
r->type = types[TINT32];
- r = nod(OLIST, c, r);
+ r = list(c, r);
on = syslook("indexstring", 0);
r = nod(OCALL, on, r);
break;
@@ -1382,7 +1518,7 @@
l = isbytearray(n->left->type);
c = nodintconst(l-1);
- r = nod(OLIST, r, c);
+ r = list(r, c);
on = syslook("byteastring", 0);
r = nod(OCALL, on, r);
break;
@@ -1499,13 +1635,13 @@
a = nodintconst(0);
r = a;
a = nodintconst(algtype(t->type)); // val algorithm
- r = nod(OLIST, a, r);
+ r = list(a, r);
a = nodintconst(algtype(t->down)); // key algorithm
- r = nod(OLIST, a, r);
+ r = list(a, r);
a = nodintconst(t->type->width); // val width
- r = nod(OLIST, a, r);
+ r = list(a, r);
a = nodintconst(t->down->width); // key width
- r = nod(OLIST, a, r);
+ r = list(a, r);
on = syslook("newmap", 1);
@@ -1541,7 +1677,7 @@
r = a;
a = n->left; // map
- r = nod(OLIST, a, r);
+ r = list(a, r);
on = syslook("mapaccess1", 1);
@@ -1579,9 +1715,9 @@
a = n->right; // val
r = a;
a = n->left->right; // key
- r = nod(OLIST, a, r);
+ r = list(a, r);
a = n->left->left; // map
- r = nod(OLIST, a, r);
+ r = list(a, r);
on = syslook("mapassign1", 1);
@@ -1608,11 +1744,11 @@
a = n->right->right; // pres
r = a;
a = n->right->left; // val
- r =nod(OLIST, a, r);
+ r =list(a, r);
a = n->left->right; // key
- r = nod(OLIST, a, r);
+ r = list(a, r);
a = n->left->left; // map
- r = nod(OLIST, a, r);
+ r = list(a, r);
on = syslook("mapassign2", 1);
@@ -1639,7 +1775,7 @@
a = n->right->right; // key
r = a;
a = n->right->left; // map
- r = nod(OLIST, a, r);
+ r = list(a, r);
on = syslook("mapaccess2", 1);
@@ -1695,9 +1831,9 @@
a = nodintconst(0);
r = a;
a = nodintconst(algtype(t->type)); // elem algorithm
- r = nod(OLIST, a, r);
+ r = list(a, r);
a = nodintconst(t->type->width); // elem width
- r = nod(OLIST, a, r);
+ r = list(a, r);
on = syslook("newchan", 1);
argtype(on, t->type); // any-1
@@ -1789,7 +1925,7 @@
a = n->right; // e
r = a;
a = n->left; // chan
- r = nod(OLIST, a, r);
+ r = list(a, r);
on = syslook("chansend1", 1);
argtype(on, t->type); // any-1
@@ -1807,7 +1943,7 @@
a = n->right; // e
r = a;
a = n->left; // chan
- r = nod(OLIST, a, r);
+ r = list(a, r);
on = syslook("chansend2", 1);
argtype(on, t->type); // any-1
@@ -1981,7 +2117,7 @@
if(n == N)
n = a;
else
- n = nod(OLIST, n, a);
+ n = list(n, a);
l = listnext(&savel);
r = listnext(&saver);
@@ -2017,7 +2153,7 @@
if(n == N)
n = a;
else
- n = nod(OLIST, n, a);
+ n = list(n, a);
l = listnext(&savel);
t = structnext(&saver);
}
@@ -2039,7 +2175,7 @@
a = old2new(nl->left, t->type);
n = a;
a = old2new(nl->right, types[TBOOL]);
- n = nod(OLIST, n, a);
+ n = list(n, a);
break;
case ORECV:
@@ -2052,7 +2188,7 @@
a = old2new(nl->left, t->type->type);
n = a;
a = old2new(nl->right, types[TBOOL]);
- n = nod(OLIST, n, a);
+ n = list(n, a);
}
n = rev(n);
return n;
@@ -2107,15 +2243,15 @@
r = rev(r);
g = rev(g);
if(g != N)
- f = nod(OLIST, g, f);
- r = nod(OLIST, f, r);
+ f = list(g, f);
+ r = list(f, r);
return r;
}
if(l->ullman < UINF) {
if(r == N)
r = l;
else
- r = nod(OLIST, l, r);
+ r = list(l, r);
goto more;
}
if(f == N) {
@@ -2131,7 +2267,7 @@
if(g == N)
g = a;
else
- g = nod(OLIST, a, g);
+ g = list(a, g);
// put normal arg assignment on list
// with fncall replaced by tempname
@@ -2139,7 +2275,7 @@
if(r == N)
r = l;
else
- r = nod(OLIST, l, r);
+ r = list(l, r);
more:
l = listnext(&save);
@@ -2256,7 +2392,7 @@
if(r == N)
r = q;
else
- r = nod(OLIST, r, q);
+ r = list(r, q);
break;
}
}
@@ -2275,7 +2411,7 @@
if(q == N)
q = l1;
else
- q = nod(OLIST, q, l1);
+ q = list(q, l1);
l1 = listnext(&save1);
}
@@ -2285,7 +2421,7 @@
if(q == N)
q = l1;
else
- q = nod(OLIST, q, l1);
+ q = list(q, l1);
l1 = listnext(&save1);
}
diff --git a/src/runtime/chan.c b/src/runtime/chan.c
index 99f9b23..9f48c5d 100644
--- a/src/runtime/chan.c
+++ b/src/runtime/chan.c
@@ -10,10 +10,13 @@
typedef struct Link Link;
typedef struct WaitQ WaitQ;
typedef struct SudoG SudoG;
+typedef struct Select Select;
+typedef struct Scase Scase;
struct SudoG
{
G* g; // g and selgen constitute
+ byte elem[8]; // synch data element
int64 selgen; // a weak pointer to g
SudoG* link;
};
@@ -29,8 +32,8 @@
uint32 elemsize;
uint32 dataqsiz; // size of the circular q
uint32 qcount; // total data in the q
- uint32 eo; // vararg of element
- uint32 po; // vararg of present bool
+ uint16 eo; // vararg of element
+ uint16 po; // vararg of present bool
Alg* elemalg; // interface for element type
Link* senddataq; // pointer for sender
Link* recvdataq; // pointer for receiver
@@ -41,14 +44,33 @@
struct Link
{
- Link* link;
- byte elem[8];
+ Link* link; // asynch queue circular linked list
+ byte elem[8]; // asynch queue data element
};
-static SudoG* dequeue(WaitQ*, Hchan*);
-static void enqueue(WaitQ*, SudoG*);
-static SudoG* allocsg(Hchan*);
-static void freesg(Hchan*, SudoG*);
+struct Scase
+{
+ Hchan* chan; // chan
+ byte* pc; // return pc
+ uint16 send; // 0-recv 1-send
+ uint16 so; // vararg of selected bool
+ byte elem[8]; // element
+};
+
+struct Select
+{
+ uint16 tcase; // total count of scase[]
+ uint16 ncase; // currently filled scase[]
+ Scase scase[1]; // one per case
+};
+
+static SudoG* dequeue(WaitQ*, Hchan*);
+static void enqueue(WaitQ*, SudoG*);
+static SudoG* allocsg(Hchan*);
+static void freesg(Hchan*, SudoG*);
+static uint32 gcd(uint32, uint32);
+static uint32 fastrand1(void);
+static uint32 fastrand2(void);
// newchan(elemsize uint32, elemalg uint32, hint uint32) (hchan *chan any);
void
@@ -134,16 +156,15 @@
sgr = dequeue(&c->recvq, c);
if(sgr != nil) {
- gr = sgr->g;
- freesg(c, sgr);
+ c->elemalg->copy(c->elemsize, sgr->elem, ae);
- c->elemalg->copy(c->elemsize, gr->elem, ae);
+ gr = sgr->g;
gr->status = Grunnable;
return;
}
- c->elemalg->copy(c->elemsize, g->elem, ae);
sgr = allocsg(c);
+ c->elemalg->copy(c->elemsize, sgr->elem, ae);
g->status = Gwaiting;
enqueue(&c->sendq, sgr);
sys·gosched();
@@ -191,9 +212,8 @@
sgr = dequeue(&c->recvq, c);
if(sgr != nil) {
gr = sgr->g;
- freesg(c, sgr);
+ c->elemalg->copy(c->elemsize, sgr->elem, ae);
- c->elemalg->copy(c->elemsize, gr->elem, ae);
gr->status = Grunnable;
*ap = true;
return;
@@ -237,18 +257,20 @@
sgs = dequeue(&c->sendq, c);
if(sgs != nil) {
- gs = sgs->g;
- freesg(c, sgs);
+ c->elemalg->copy(c->elemsize, ae, sgs->elem);
- c->elemalg->copy(c->elemsize, ae, gs->elem);
+ gs = sgs->g;
gs->status = Grunnable;
+
+ freesg(c, sgs);
return;
}
sgs = allocsg(c);
g->status = Gwaiting;
enqueue(&c->recvq, sgs);
sys·gosched();
- c->elemalg->copy(c->elemsize, ae, g->elem);
+ c->elemalg->copy(c->elemsize, ae, sgs->elem);
+ freesg(c, sgs);
return;
asynch:
@@ -291,11 +313,12 @@
sgs = dequeue(&c->sendq, c);
if(sgs != nil) {
- gs = sgs->g;
- freesg(c, sgs);
+ c->elemalg->copy(c->elemsize, ae, sgs->elem);
- c->elemalg->copy(c->elemsize, ae, gs->elem);
+ gs = sgs->g;
gs->status = Grunnable;
+
+ freesg(c, sgs);
*ap = true;
return;
}
@@ -320,6 +343,150 @@
*ap = true;
}
+// newselect(size uint32) (sel *byte);
+void
+sys·newselect(int32 size, Select *sel)
+{
+ int32 n;
+
+ n = 0;
+ if(size > 1)
+ n = size-1;
+ sel = mal(sizeof(*sel) + n*sizeof(sel->scase[0]));
+ sel->tcase = size;
+ sel->ncase = 0;
+ FLUSH(&sel);
+ if(debug) {
+ prints("newselect s=");
+ sys·printpointer(sel);
+ prints("\n");
+ }
+}
+
+// selectsend(sel *byte, hchan *chan any, elem any) (selected bool);
+void
+sys·selectsend(Select *sel, Hchan *c, ...)
+{
+ int32 i, eo;
+ Scase *cas;
+ byte *as, *ae;
+
+ // return val, selected, is preset to false
+ if(c == nil)
+ return;
+
+ i = sel->ncase;
+ if(i >= sel->tcase)
+ throw("selectsend: too many cases");
+ sel->ncase = i+1;
+ cas = &sel->scase[i];
+
+ cas->pc = sys·getcallerpc(&sel);
+ cas->chan = c;
+
+ eo = rnd(sizeof(sel), sizeof(c));
+ eo = rnd(eo+sizeof(c), c->elemsize);
+ cas->so = rnd(eo+c->elemsize, 1);
+ cas->send = 1;
+
+ ae = (byte*)&sel + eo;
+ c->elemalg->copy(c->elemsize, cas->elem, ae);
+
+ as = (byte*)&sel + cas->so;
+ *as = false;
+
+ if(debug) {
+ prints("newselect s=");
+ sys·printpointer(sel);
+ prints(" pc=");
+ sys·printpointer(cas->pc);
+ prints(" chan=");
+ sys·printpointer(cas->chan);
+ prints(" po=");
+ sys·printint(cas->so);
+ prints(" send=");
+ sys·printint(cas->send);
+ prints("\n");
+ }
+}
+
+// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
+void
+sys·selectrecv(Select *sel, Hchan *c, ...)
+{
+ throw("selectrecv");
+}
+
+// selectgo(sel *byte);
+void
+sys·selectgo(Select *sel)
+{
+ uint32 p, o, i;
+ Scase *cas;
+ Hchan *c;
+
+ byte *ae, *as;
+ SudoG *sgr;
+ G *gr;
+
+ if(sel->ncase < 1) {
+ throw("selectgo: no cases");
+ }
+
+ // select a (relative) prime
+ for(i=0;; i++) {
+ p = fastrand1();
+ if(gcd(p, sel->ncase) == 1)
+ break;
+ if(i > 1000) {
+ throw("selectgo: failed to select prime");
+ }
+ }
+ o = fastrand2();
+
+ p %= sel->ncase;
+ o %= sel->ncase;
+
+ // pass 1 - look for something that can go
+ for(i=0; i<sel->ncase; i++) {
+ cas = &sel->scase[o];
+ c = cas->chan;
+ if(cas->send) {
+ if(c->dataqsiz > 0) {
+ throw("selectgo: asynch");
+ }
+ sgr = dequeue(&c->recvq, c);
+ if(sgr == nil)
+ continue;
+
+ c->elemalg->copy(c->elemsize, sgr->elem, cas->elem);
+ gr = sgr->g;
+ gr->status = Grunnable;
+
+ goto retc;
+ }
+
+ o += p;
+ if(o >= sel->ncase)
+ o -= sel->ncase;
+ }
+
+ if(debug) {
+ prints("selectgo s=");
+ sys·printpointer(sel);
+ prints(" p=");
+ sys·printpointer((void*)p);
+ prints("\n");
+ }
+
+ throw("selectgo");
+
+retc:
+ sys·setcallerpc(&sel, cas->pc);
+ as = (byte*)&sel + cas->so;
+ *as = true;
+}
+
static SudoG*
dequeue(WaitQ *q, Hchan *c)
{
@@ -377,3 +544,41 @@
sg->link = c->free;
c->free = sg;
}
+
+static uint32
+gcd(uint32 u, uint32 v)
+{
+ for(;;) {
+ if(u > v) {
+ if(v == 0)
+ return u;
+ u = u%v;
+ continue;
+ }
+ if(u == 0)
+ return v;
+ v = v%u;
+ }
+}
+
+static uint32
+fastrand1(void)
+{
+ static uint32 x = 0x49f6428aUL;
+
+ x += x;
+ if(x & 0x80000000L)
+ x ^= 0x88888eefUL;
+ return x;
+}
+
+static uint32
+fastrand2(void)
+{
+ static uint32 x = 0x49f6428aUL;
+
+ x += x;
+ if(x & 0x80000000L)
+ x ^= 0xfafd871bUL;
+ return x;
+}
diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h
index df14b76..fe6ef54 100644
--- a/src/runtime/runtime.h
+++ b/src/runtime/runtime.h
@@ -110,7 +110,6 @@
int32 status;
int32 goid;
int64 selgen; // valid sudog pointer
- byte elem[8]; // transfer element for chan
};
struct M
{
@@ -205,6 +204,7 @@
void sys·breakpoint(void);
uint8* sys·mmap(byte*, uint32, int32, int32, int32, uint32);
void sys·memclr(byte*, uint32);
+void sys·setcallerpc(void*, void*);
void* sys·getcallerpc(void*);
void sys·sigaction(int64, void*, void*);
void sys·rt_sigaction(int64, void*, void*, uint64);
diff --git a/src/runtime/sys_amd64_darwin.s b/src/runtime/sys_amd64_darwin.s
index 26ceaaf..39549cb 100644
--- a/src/runtime/sys_amd64_darwin.s
+++ b/src/runtime/sys_amd64_darwin.s
@@ -110,6 +110,12 @@
RET
TEXT sys·getcallerpc+0(SB),1,$0
- MOVQ x+0(FP),AX
- MOVQ -8(AX),AX
+ MOVQ x+0(FP),AX // addr of first arg
+ MOVQ -8(AX),AX // get calling pc
+ RET
+
+TEXT sys·setcallerpc+0(SB),1,$0
+ MOVQ x+0(FP),AX // addr of first arg
+ MOVQ x+8(FP), BX
+ MOVQ BX, -8(AX) // set calling pc
RET
diff --git a/src/runtime/sys_amd64_linux.s b/src/runtime/sys_amd64_linux.s
index e98ca52..106159d 100644
--- a/src/runtime/sys_amd64_linux.s
+++ b/src/runtime/sys_amd64_linux.s
@@ -114,6 +114,12 @@
RET
TEXT sys·getcallerpc+0(SB),1,$0
- MOVQ x+0(FP),AX
- MOVQ -8(AX),AX
+ MOVQ x+0(FP),AX // addr of first arg
+ MOVQ -8(AX),AX // get calling pc
+ RET
+
+TEXT sys·setcallerpc+0(SB),1,$0
+ MOVQ x+0(FP),AX // addr of first arg
+ MOVQ x+8(FP), BX
+ MOVQ BX, -8(AX) // set calling pc
RET