| // Copyright 2016 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #define _ALL_SOURCE 1 |
| #include <threads.h> |
| #include <zircon/process.h> |
| #include <zircon/types.h> |
| |
| #include "libc.h" |
| |
| static mtx_t startup_handles_lock = MTX_INIT; |
| static uint32_t startup_handles_num; |
| static zx_handle_t* startup_handles; |
| static uint32_t* startup_handles_info; |
| |
| static void shave_front(void) { |
| while (startup_handles_num > 0 && startup_handles[0] == ZX_HANDLE_INVALID) { |
| --startup_handles_num; |
| ++startup_handles; |
| ++startup_handles_info; |
| } |
| } |
| |
| static void shave_back(void) { |
| while (startup_handles_num > 0 && startup_handles[startup_handles_num - 1] == ZX_HANDLE_INVALID) |
| --startup_handles_num; |
| } |
| |
| // This is called only once at startup, so it doesn't need locking. |
| ATTR_LIBC_VISIBILITY |
| void __libc_startup_handles_init(uint32_t nhandles, zx_handle_t handles[], uint32_t handle_info[]) { |
| startup_handles_num = nhandles; |
| startup_handles = handles; |
| startup_handles_info = handle_info; |
| shave_front(); |
| shave_back(); |
| } |
| |
| __EXPORT |
| zx_handle_t zx_take_startup_handle(uint32_t hnd_info) { |
| zx_handle_t result = ZX_HANDLE_INVALID; |
| mtx_lock(&startup_handles_lock); |
| for (uint32_t i = 0; i < startup_handles_num; ++i) { |
| if (startup_handles_info[i] == hnd_info) { |
| result = startup_handles[i]; |
| startup_handles[i] = ZX_HANDLE_INVALID; |
| startup_handles_info[i] = 0; |
| if (i == 0) |
| shave_front(); |
| else if (i == startup_handles_num - 1) |
| shave_back(); |
| break; |
| } |
| } |
| mtx_unlock(&startup_handles_lock); |
| return result; |
| } |