github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/kernel/semaphore/semaphore.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package semaphore implements System V semaphores. 16 package semaphore 17 18 import ( 19 "fmt" 20 21 "github.com/SagerNet/gvisor/pkg/abi/linux" 22 "github.com/SagerNet/gvisor/pkg/context" 23 "github.com/SagerNet/gvisor/pkg/errors/linuxerr" 24 "github.com/SagerNet/gvisor/pkg/log" 25 "github.com/SagerNet/gvisor/pkg/sentry/fs" 26 "github.com/SagerNet/gvisor/pkg/sentry/kernel/auth" 27 ktime "github.com/SagerNet/gvisor/pkg/sentry/kernel/time" 28 "github.com/SagerNet/gvisor/pkg/sync" 29 "github.com/SagerNet/gvisor/pkg/syserror" 30 ) 31 32 const ( 33 // Maximum semaphore value. 34 valueMax = linux.SEMVMX 35 36 // Maximum number of semaphore sets. 37 setsMax = linux.SEMMNI 38 39 // Maximum number of semaphores in a semaphore set. 40 semsMax = linux.SEMMSL 41 42 // Maximum number of semaphores in all semaphore sets. 43 semsTotalMax = linux.SEMMNS 44 ) 45 46 // Registry maintains a set of semaphores that can be found by key or ID. 47 // 48 // +stateify savable 49 type Registry struct { 50 // userNS owning the ipc name this registry belongs to. Immutable. 51 userNS *auth.UserNamespace 52 // mu protects all fields below. 53 mu sync.Mutex `state:"nosave"` 54 semaphores map[int32]*Set 55 lastIDUsed int32 56 // indexes maintains a mapping between a set's index in virtual array and 57 // its identifier. 58 indexes map[int32]int32 59 } 60 61 // Set represents a set of semaphores that can be operated atomically. 62 // 63 // +stateify savable 64 type Set struct { 65 // registry owning this sem set. Immutable. 66 registry *Registry 67 68 // Id is a handle that identifies the set. 69 ID int32 70 71 // key is an user provided key that can be shared between processes. 72 key int32 73 74 // creator is the user that created the set. Immutable. 75 creator fs.FileOwner 76 77 // mu protects all fields below. 78 mu sync.Mutex `state:"nosave"` 79 owner fs.FileOwner 80 perms fs.FilePermissions 81 opTime ktime.Time 82 changeTime ktime.Time 83 84 // sems holds all semaphores in the set. The slice itself is immutable after 85 // it's been set, however each 'sem' object in the slice requires 'mu' lock. 86 sems []sem 87 88 // dead is set to true when the set is removed and can't be reached anymore. 89 // All waiters must wake up and fail when set is dead. 90 dead bool 91 } 92 93 // sem represents a single semaphore from a set. 94 // 95 // +stateify savable 96 type sem struct { 97 value int16 98 waiters waiterList `state:"zerovalue"` 99 pid int32 100 } 101 102 // waiter represents a caller that is waiting for the semaphore value to 103 // become positive or zero. 104 // 105 // +stateify savable 106 type waiter struct { 107 waiterEntry 108 109 // value represents how much resource the waiter needs to wake up. 110 // The value is either 0 or negative. 111 value int16 112 ch chan struct{} 113 } 114 115 // NewRegistry creates a new semaphore set registry. 116 func NewRegistry(userNS *auth.UserNamespace) *Registry { 117 return &Registry{ 118 userNS: userNS, 119 semaphores: make(map[int32]*Set), 120 indexes: make(map[int32]int32), 121 } 122 } 123 124 // FindOrCreate searches for a semaphore set that matches 'key'. If not found, 125 // it may create a new one if requested. If private is true, key is ignored and 126 // a new set is always created. If create is false, it fails if a set cannot 127 // be found. If exclusive is true, it fails if a set with the same key already 128 // exists. 129 func (r *Registry) FindOrCreate(ctx context.Context, key, nsems int32, mode linux.FileMode, private, create, exclusive bool) (*Set, error) { 130 if nsems < 0 || nsems > semsMax { 131 return nil, linuxerr.EINVAL 132 } 133 134 r.mu.Lock() 135 defer r.mu.Unlock() 136 137 if !private { 138 // Look up an existing semaphore. 139 if set := r.findByKey(key); set != nil { 140 set.mu.Lock() 141 defer set.mu.Unlock() 142 143 // Check that caller can access semaphore set. 144 creds := auth.CredentialsFromContext(ctx) 145 if !set.checkPerms(creds, fs.PermsFromMode(mode)) { 146 return nil, linuxerr.EACCES 147 } 148 149 // Validate parameters. 150 if nsems > int32(set.Size()) { 151 return nil, linuxerr.EINVAL 152 } 153 if create && exclusive { 154 return nil, syserror.EEXIST 155 } 156 return set, nil 157 } 158 159 if !create { 160 // Semaphore not found and should not be created. 161 return nil, syserror.ENOENT 162 } 163 } 164 165 // Zero is only valid if an existing set is found. 166 if nsems == 0 { 167 return nil, linuxerr.EINVAL 168 } 169 170 // Apply system limits. 171 // 172 // Map semaphores and map indexes in a registry are of the same size, 173 // check map semaphores only here for the system limit. 174 if len(r.semaphores) >= setsMax { 175 return nil, syserror.ENOSPC 176 } 177 if r.totalSems() > int(semsTotalMax-nsems) { 178 return nil, syserror.ENOSPC 179 } 180 181 // Finally create a new set. 182 owner := fs.FileOwnerFromContext(ctx) 183 perms := fs.FilePermsFromMode(mode) 184 return r.newSet(ctx, key, owner, owner, perms, nsems) 185 } 186 187 // IPCInfo returns information about system-wide semaphore limits and parameters. 188 func (r *Registry) IPCInfo() *linux.SemInfo { 189 return &linux.SemInfo{ 190 SemMap: linux.SEMMAP, 191 SemMni: linux.SEMMNI, 192 SemMns: linux.SEMMNS, 193 SemMnu: linux.SEMMNU, 194 SemMsl: linux.SEMMSL, 195 SemOpm: linux.SEMOPM, 196 SemUme: linux.SEMUME, 197 SemUsz: linux.SEMUSZ, 198 SemVmx: linux.SEMVMX, 199 SemAem: linux.SEMAEM, 200 } 201 } 202 203 // SemInfo returns a seminfo structure containing the same information as 204 // for IPC_INFO, except that SemUsz field returns the number of existing 205 // semaphore sets, and SemAem field returns the number of existing semaphores. 206 func (r *Registry) SemInfo() *linux.SemInfo { 207 r.mu.Lock() 208 defer r.mu.Unlock() 209 210 info := r.IPCInfo() 211 info.SemUsz = uint32(len(r.semaphores)) 212 info.SemAem = uint32(r.totalSems()) 213 214 return info 215 } 216 217 // HighestIndex returns the index of the highest used entry in 218 // the kernel's array. 219 func (r *Registry) HighestIndex() int32 { 220 r.mu.Lock() 221 defer r.mu.Unlock() 222 223 // By default, highest used index is 0 even though 224 // there is no semaphore set. 225 var highestIndex int32 226 for index := range r.indexes { 227 if index > highestIndex { 228 highestIndex = index 229 } 230 } 231 return highestIndex 232 } 233 234 // RemoveID removes set with give 'id' from the registry and marks the set as 235 // dead. All waiters will be awakened and fail. 236 func (r *Registry) RemoveID(id int32, creds *auth.Credentials) error { 237 r.mu.Lock() 238 defer r.mu.Unlock() 239 240 set := r.semaphores[id] 241 if set == nil { 242 return linuxerr.EINVAL 243 } 244 index, found := r.findIndexByID(id) 245 if !found { 246 // Inconsistent state. 247 panic(fmt.Sprintf("unable to find an index for ID: %d", id)) 248 } 249 250 set.mu.Lock() 251 defer set.mu.Unlock() 252 253 // "The effective user ID of the calling process must match the creator or 254 // owner of the semaphore set, or the caller must be privileged." 255 if !set.checkCredentials(creds) && !set.checkCapability(creds) { 256 return linuxerr.EACCES 257 } 258 259 delete(r.semaphores, set.ID) 260 delete(r.indexes, index) 261 set.destroy() 262 return nil 263 } 264 265 func (r *Registry) newSet(ctx context.Context, key int32, owner, creator fs.FileOwner, perms fs.FilePermissions, nsems int32) (*Set, error) { 266 set := &Set{ 267 registry: r, 268 key: key, 269 owner: owner, 270 creator: owner, 271 perms: perms, 272 changeTime: ktime.NowFromContext(ctx), 273 sems: make([]sem, nsems), 274 } 275 276 // Find the next available ID. 277 for id := r.lastIDUsed + 1; id != r.lastIDUsed; id++ { 278 // Handle wrap around. 279 if id < 0 { 280 id = 0 281 continue 282 } 283 if r.semaphores[id] == nil { 284 index, found := r.findFirstAvailableIndex() 285 if !found { 286 panic("unable to find an available index") 287 } 288 r.indexes[index] = id 289 r.lastIDUsed = id 290 r.semaphores[id] = set 291 set.ID = id 292 return set, nil 293 } 294 } 295 296 log.Warningf("Semaphore map is full, they must be leaking") 297 return nil, syserror.ENOMEM 298 } 299 300 // FindByID looks up a set given an ID. 301 func (r *Registry) FindByID(id int32) *Set { 302 r.mu.Lock() 303 defer r.mu.Unlock() 304 return r.semaphores[id] 305 } 306 307 // FindByIndex looks up a set given an index. 308 func (r *Registry) FindByIndex(index int32) *Set { 309 r.mu.Lock() 310 defer r.mu.Unlock() 311 312 id, present := r.indexes[index] 313 if !present { 314 return nil 315 } 316 return r.semaphores[id] 317 } 318 319 func (r *Registry) findByKey(key int32) *Set { 320 for _, v := range r.semaphores { 321 if v.key == key { 322 return v 323 } 324 } 325 return nil 326 } 327 328 func (r *Registry) findIndexByID(id int32) (int32, bool) { 329 for k, v := range r.indexes { 330 if v == id { 331 return k, true 332 } 333 } 334 return 0, false 335 } 336 337 func (r *Registry) findFirstAvailableIndex() (int32, bool) { 338 for index := int32(0); index < setsMax; index++ { 339 if _, present := r.indexes[index]; !present { 340 return index, true 341 } 342 } 343 return 0, false 344 } 345 346 func (r *Registry) totalSems() int { 347 totalSems := 0 348 for _, v := range r.semaphores { 349 totalSems += v.Size() 350 } 351 return totalSems 352 } 353 354 func (s *Set) findSem(num int32) *sem { 355 if num < 0 || int(num) >= s.Size() { 356 return nil 357 } 358 return &s.sems[num] 359 } 360 361 // Size returns the number of semaphores in the set. Size is immutable. 362 func (s *Set) Size() int { 363 return len(s.sems) 364 } 365 366 // Change changes some fields from the set atomically. 367 func (s *Set) Change(ctx context.Context, creds *auth.Credentials, owner fs.FileOwner, perms fs.FilePermissions) error { 368 s.mu.Lock() 369 defer s.mu.Unlock() 370 371 // "The effective UID of the calling process must match the owner or creator 372 // of the semaphore set, or the caller must be privileged." 373 if !s.checkCredentials(creds) && !s.checkCapability(creds) { 374 return linuxerr.EACCES 375 } 376 377 s.owner = owner 378 s.perms = perms 379 s.changeTime = ktime.NowFromContext(ctx) 380 return nil 381 } 382 383 // GetStat extracts semid_ds information from the set. 384 func (s *Set) GetStat(creds *auth.Credentials) (*linux.SemidDS, error) { 385 // "The calling process must have read permission on the semaphore set." 386 return s.semStat(creds, fs.PermMask{Read: true}) 387 } 388 389 // GetStatAny extracts semid_ds information from the set without requiring read access. 390 func (s *Set) GetStatAny(creds *auth.Credentials) (*linux.SemidDS, error) { 391 return s.semStat(creds, fs.PermMask{}) 392 } 393 394 func (s *Set) semStat(creds *auth.Credentials, permMask fs.PermMask) (*linux.SemidDS, error) { 395 s.mu.Lock() 396 defer s.mu.Unlock() 397 398 if !s.checkPerms(creds, permMask) { 399 return nil, linuxerr.EACCES 400 } 401 402 return &linux.SemidDS{ 403 SemPerm: linux.IPCPerm{ 404 Key: uint32(s.key), 405 UID: uint32(creds.UserNamespace.MapFromKUID(s.owner.UID)), 406 GID: uint32(creds.UserNamespace.MapFromKGID(s.owner.GID)), 407 CUID: uint32(creds.UserNamespace.MapFromKUID(s.creator.UID)), 408 CGID: uint32(creds.UserNamespace.MapFromKGID(s.creator.GID)), 409 Mode: uint16(s.perms.LinuxMode()), 410 Seq: 0, // IPC sequence not supported. 411 }, 412 SemOTime: s.opTime.TimeT(), 413 SemCTime: s.changeTime.TimeT(), 414 SemNSems: uint64(s.Size()), 415 }, nil 416 } 417 418 // SetVal overrides a semaphore value, waking up waiters as needed. 419 func (s *Set) SetVal(ctx context.Context, num int32, val int16, creds *auth.Credentials, pid int32) error { 420 if val < 0 || val > valueMax { 421 return syserror.ERANGE 422 } 423 424 s.mu.Lock() 425 defer s.mu.Unlock() 426 427 // "The calling process must have alter permission on the semaphore set." 428 if !s.checkPerms(creds, fs.PermMask{Write: true}) { 429 return linuxerr.EACCES 430 } 431 432 sem := s.findSem(num) 433 if sem == nil { 434 return syserror.ERANGE 435 } 436 437 // TODO(github.com/SagerNet/issue/137): Clear undo entries in all processes. 438 sem.value = val 439 sem.pid = pid 440 s.changeTime = ktime.NowFromContext(ctx) 441 sem.wakeWaiters() 442 return nil 443 } 444 445 // SetValAll overrides all semaphores values, waking up waiters as needed. It also 446 // sets semaphore's PID which was fixed in Linux 4.6. 447 // 448 // 'len(vals)' must be equal to 's.Size()'. 449 func (s *Set) SetValAll(ctx context.Context, vals []uint16, creds *auth.Credentials, pid int32) error { 450 if len(vals) != s.Size() { 451 panic(fmt.Sprintf("vals length (%d) different that Set.Size() (%d)", len(vals), s.Size())) 452 } 453 454 for _, val := range vals { 455 if val > valueMax { 456 return syserror.ERANGE 457 } 458 } 459 460 s.mu.Lock() 461 defer s.mu.Unlock() 462 463 // "The calling process must have alter permission on the semaphore set." 464 if !s.checkPerms(creds, fs.PermMask{Write: true}) { 465 return linuxerr.EACCES 466 } 467 468 for i, val := range vals { 469 sem := &s.sems[i] 470 471 // TODO(github.com/SagerNet/issue/137): Clear undo entries in all processes. 472 sem.value = int16(val) 473 sem.pid = pid 474 sem.wakeWaiters() 475 } 476 s.changeTime = ktime.NowFromContext(ctx) 477 return nil 478 } 479 480 // GetVal returns a semaphore value. 481 func (s *Set) GetVal(num int32, creds *auth.Credentials) (int16, error) { 482 s.mu.Lock() 483 defer s.mu.Unlock() 484 485 // "The calling process must have read permission on the semaphore set." 486 if !s.checkPerms(creds, fs.PermMask{Read: true}) { 487 return 0, linuxerr.EACCES 488 } 489 490 sem := s.findSem(num) 491 if sem == nil { 492 return 0, syserror.ERANGE 493 } 494 return sem.value, nil 495 } 496 497 // GetValAll returns value for all semaphores. 498 func (s *Set) GetValAll(creds *auth.Credentials) ([]uint16, error) { 499 s.mu.Lock() 500 defer s.mu.Unlock() 501 502 // "The calling process must have read permission on the semaphore set." 503 if !s.checkPerms(creds, fs.PermMask{Read: true}) { 504 return nil, linuxerr.EACCES 505 } 506 507 vals := make([]uint16, s.Size()) 508 for i, sem := range s.sems { 509 vals[i] = uint16(sem.value) 510 } 511 return vals, nil 512 } 513 514 // GetPID returns the PID set when performing operations in the semaphore. 515 func (s *Set) GetPID(num int32, creds *auth.Credentials) (int32, error) { 516 s.mu.Lock() 517 defer s.mu.Unlock() 518 519 // "The calling process must have read permission on the semaphore set." 520 if !s.checkPerms(creds, fs.PermMask{Read: true}) { 521 return 0, linuxerr.EACCES 522 } 523 524 sem := s.findSem(num) 525 if sem == nil { 526 return 0, syserror.ERANGE 527 } 528 return sem.pid, nil 529 } 530 531 func (s *Set) countWaiters(num int32, creds *auth.Credentials, pred func(w *waiter) bool) (uint16, error) { 532 s.mu.Lock() 533 defer s.mu.Unlock() 534 535 // The calling process must have read permission on the semaphore set. 536 if !s.checkPerms(creds, fs.PermMask{Read: true}) { 537 return 0, linuxerr.EACCES 538 } 539 540 sem := s.findSem(num) 541 if sem == nil { 542 return 0, syserror.ERANGE 543 } 544 var cnt uint16 545 for w := sem.waiters.Front(); w != nil; w = w.Next() { 546 if pred(w) { 547 cnt++ 548 } 549 } 550 return cnt, nil 551 } 552 553 // CountZeroWaiters returns number of waiters waiting for the sem's value to increase. 554 func (s *Set) CountZeroWaiters(num int32, creds *auth.Credentials) (uint16, error) { 555 return s.countWaiters(num, creds, func(w *waiter) bool { 556 return w.value == 0 557 }) 558 } 559 560 // CountNegativeWaiters returns number of waiters waiting for the sem to go to zero. 561 func (s *Set) CountNegativeWaiters(num int32, creds *auth.Credentials) (uint16, error) { 562 return s.countWaiters(num, creds, func(w *waiter) bool { 563 return w.value < 0 564 }) 565 } 566 567 // ExecuteOps attempts to execute a list of operations to the set. It only 568 // succeeds when all operations can be applied. No changes are made if it fails. 569 // 570 // On failure, it may return an error (retries are hopeless) or it may return 571 // a channel that can be waited on before attempting again. 572 func (s *Set) ExecuteOps(ctx context.Context, ops []linux.Sembuf, creds *auth.Credentials, pid int32) (chan struct{}, int32, error) { 573 s.mu.Lock() 574 defer s.mu.Unlock() 575 576 // Did it race with a removal operation? 577 if s.dead { 578 return nil, 0, syserror.EIDRM 579 } 580 581 // Validate the operations. 582 readOnly := true 583 for _, op := range ops { 584 if s.findSem(int32(op.SemNum)) == nil { 585 return nil, 0, linuxerr.EFBIG 586 } 587 if op.SemOp != 0 { 588 readOnly = false 589 } 590 } 591 592 if !s.checkPerms(creds, fs.PermMask{Read: readOnly, Write: !readOnly}) { 593 return nil, 0, linuxerr.EACCES 594 } 595 596 ch, num, err := s.executeOps(ctx, ops, pid) 597 if err != nil { 598 return nil, 0, err 599 } 600 return ch, num, nil 601 } 602 603 func (s *Set) executeOps(ctx context.Context, ops []linux.Sembuf, pid int32) (chan struct{}, int32, error) { 604 // Changes to semaphores go to this slice temporarily until they all succeed. 605 tmpVals := make([]int16, len(s.sems)) 606 for i := range s.sems { 607 tmpVals[i] = s.sems[i].value 608 } 609 610 for _, op := range ops { 611 sem := &s.sems[op.SemNum] 612 if op.SemOp == 0 { 613 // Handle 'wait for zero' operation. 614 if tmpVals[op.SemNum] != 0 { 615 // Semaphore isn't 0, must wait. 616 if op.SemFlg&linux.IPC_NOWAIT != 0 { 617 return nil, 0, syserror.ErrWouldBlock 618 } 619 620 w := newWaiter(op.SemOp) 621 sem.waiters.PushBack(w) 622 return w.ch, int32(op.SemNum), nil 623 } 624 } else { 625 if op.SemOp < 0 { 626 // Handle 'wait' operation. 627 if -op.SemOp > valueMax { 628 return nil, 0, syserror.ERANGE 629 } 630 if -op.SemOp > tmpVals[op.SemNum] { 631 // Not enough resources, must wait. 632 if op.SemFlg&linux.IPC_NOWAIT != 0 { 633 return nil, 0, syserror.ErrWouldBlock 634 } 635 636 w := newWaiter(op.SemOp) 637 sem.waiters.PushBack(w) 638 return w.ch, int32(op.SemNum), nil 639 } 640 } else { 641 // op.SemOp > 0: Handle 'signal' operation. 642 if tmpVals[op.SemNum] > valueMax-op.SemOp { 643 return nil, 0, syserror.ERANGE 644 } 645 } 646 647 tmpVals[op.SemNum] += op.SemOp 648 } 649 } 650 651 // All operations succeeded, apply them. 652 // TODO(github.com/SagerNet/issue/137): handle undo operations. 653 for i, v := range tmpVals { 654 s.sems[i].value = v 655 s.sems[i].wakeWaiters() 656 s.sems[i].pid = pid 657 } 658 s.opTime = ktime.NowFromContext(ctx) 659 return nil, 0, nil 660 } 661 662 // AbortWait notifies that a waiter is giving up and will not wait on the 663 // channel anymore. 664 func (s *Set) AbortWait(num int32, ch chan struct{}) { 665 s.mu.Lock() 666 defer s.mu.Unlock() 667 668 sem := &s.sems[num] 669 for w := sem.waiters.Front(); w != nil; w = w.Next() { 670 if w.ch == ch { 671 sem.waiters.Remove(w) 672 return 673 } 674 } 675 // Waiter may not be found in case it raced with wakeWaiters(). 676 } 677 678 func (s *Set) checkCredentials(creds *auth.Credentials) bool { 679 return s.owner.UID == creds.EffectiveKUID || 680 s.owner.GID == creds.EffectiveKGID || 681 s.creator.UID == creds.EffectiveKUID || 682 s.creator.GID == creds.EffectiveKGID 683 } 684 685 func (s *Set) checkCapability(creds *auth.Credentials) bool { 686 return creds.HasCapabilityIn(linux.CAP_IPC_OWNER, s.registry.userNS) && creds.UserNamespace.MapFromKUID(s.owner.UID).Ok() 687 } 688 689 func (s *Set) checkPerms(creds *auth.Credentials, reqPerms fs.PermMask) bool { 690 // Are we owner, or in group, or other? 691 p := s.perms.Other 692 if s.owner.UID == creds.EffectiveKUID { 693 p = s.perms.User 694 } else if creds.InGroup(s.owner.GID) { 695 p = s.perms.Group 696 } 697 698 // Are permissions satisfied without capability checks? 699 if p.SupersetOf(reqPerms) { 700 return true 701 } 702 703 return s.checkCapability(creds) 704 } 705 706 // destroy destroys the set. 707 // 708 // Preconditions: Caller must hold 's.mu'. 709 func (s *Set) destroy() { 710 // Notify all waiters. They will fail on the next attempt to execute 711 // operations and return error. 712 s.dead = true 713 for _, s := range s.sems { 714 for w := s.waiters.Front(); w != nil; w = w.Next() { 715 w.ch <- struct{}{} 716 } 717 s.waiters.Reset() 718 } 719 } 720 721 func abs(val int16) int16 { 722 if val < 0 { 723 return -val 724 } 725 return val 726 } 727 728 // wakeWaiters goes over all waiters and checks which of them can be notified. 729 func (s *sem) wakeWaiters() { 730 // Note that this will release all waiters waiting for 0 too. 731 for w := s.waiters.Front(); w != nil; { 732 if s.value < abs(w.value) { 733 // Still blocked, skip it. 734 w = w.Next() 735 continue 736 } 737 w.ch <- struct{}{} 738 old := w 739 w = w.Next() 740 s.waiters.Remove(old) 741 } 742 } 743 744 func newWaiter(val int16) *waiter { 745 return &waiter{ 746 value: val, 747 ch: make(chan struct{}, 1), 748 } 749 }