| // Copyright 2022 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package zx |
| |
| var threadQueue struct { |
| writer, reader Channel |
| } |
| |
| // init_threads_channel initializes a channel that is used as buffer for created |
| // threads. It must be called from os_init. |
| //go:nosplit |
| func init_threads_channel() { |
| if status := Sys_channel_create(0, threadQueue.writer.Handle(), threadQueue.reader.Handle()); status != ErrOk { |
| // NB: Can't allocate here to provide status in panic. |
| panic("failed to create threads channel") |
| } |
| } |
| |
| // notify_new_thread is called by the runtime whenever a new thread is created |
| // in minit. It duplicates the handle and stores it in the threadQueue channels |
| // for later retrieval by applications. We can't do anything a lot fancier than |
| // this because minit is a very restricted environment where we can't allocate |
| // or do much else. |
| //go:nosplit |
| func notify_new_thread(h int32) { |
| var dup Handle |
| // Duplicate the handle with the minimum set of rights to accomplish |
| // exposing the threads to applications and installing thread profiles. |
| if status := Sys_handle_duplicate(Handle(h), RightManageThread|RightTransfer, &dup); status != ErrOk { |
| // NB: Can't allocate here to provide status in panic. |
| panic("failed to duplicate thread handle") |
| } |
| if status := Sys_channel_write(threadQueue.writer.Handle().Load(), 0, nil, 0, &dup, 1); status != ErrOk { |
| // NB: Can't allocate here to provide status in panic. |
| panic("failed to write thread to channel") |
| } |
| } |
| |
| // GetThreadsChannel returns a reference to a channel that will be enqueued with |
| // a zero-byte single-handle message for every thread that the runtime creates. |
| // Applications may read from this channel to retrieve handles to the runtime |
| // threads. |
| // |
| // Closing this channel may cause the runtime to panic. Writing to this channel |
| // has no effect but increasing process memory consumption, there's nothing |
| // reading the others side. |
| func GetThreadsChannel() *Channel { |
| return &threadQueue.reader |
| } |