1 /* 2 * Capability allocation and management. 3 * 4 * Copyright (C) 2019, 2021, 2022, 2023 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include <l4/re/c/util/cap_alloc.h> 23 #include <l4/re/consts.h> 24 #include <l4/sys/err.h> 25 #include <l4/sys/task.h> 26 27 #include "cap_alloc.h" 28 #include "semaphore.h" 29 30 31 32 /* Semaphore used if threading has been initialised by ipc_cap_alloc_init. */ 33 34 l4_cap_idx_t ipc_cap_alloc_semaphore = L4_INVALID_CAP; 35 36 37 38 /* Reserve and return a capability index. */ 39 40 l4_cap_idx_t ipc_cap_alloc() 41 { 42 l4_cap_idx_t cap; 43 long err; 44 45 /* Allocate a capability in the critical section, then return. */ 46 47 err = ipc_semaphore_down(ipc_cap_alloc_semaphore); 48 if (err) 49 return L4_INVALID_CAP; 50 51 cap = l4re_util_cap_alloc(); 52 53 ipc_semaphore_up(ipc_cap_alloc_semaphore); 54 55 return cap; 56 } 57 58 /* Reserve and return many capability indexes. */ 59 60 long ipc_cap_alloc_many(l4_cap_idx_t caps[], int count) 61 { 62 int i; 63 long err; 64 65 /* Allocate a capability in the critical section, then return. */ 66 67 err = ipc_semaphore_down(ipc_cap_alloc_semaphore); 68 if (err) 69 return err; 70 71 for (i = 0; i < count; i++) 72 { 73 caps[i] = l4re_util_cap_alloc(); 74 75 if (l4_is_invalid_cap(caps[i])) 76 { 77 err = -L4_ENOMEM; 78 break; 79 } 80 } 81 82 /* Free allocated capabilities if not all could be allocated. */ 83 84 if (err) 85 for (; i >= 0; i--) 86 l4re_util_cap_free(caps[i]); 87 88 ipc_semaphore_up(ipc_cap_alloc_semaphore); 89 90 return err; 91 } 92 93 /* Release a capability. */ 94 95 int ipc_cap_free(l4_cap_idx_t cap) 96 { 97 long err; 98 99 err = ipc_semaphore_down(ipc_cap_alloc_semaphore); 100 if (err) 101 return 0; 102 103 l4re_util_cap_free(cap); 104 105 ipc_semaphore_up(ipc_cap_alloc_semaphore); 106 107 return 1; 108 } 109 110 /* Free the indicated capability and unmap it. */ 111 112 int ipc_cap_free_um(l4_cap_idx_t cap) 113 { 114 long err; 115 116 err = ipc_semaphore_down(ipc_cap_alloc_semaphore); 117 if (err) 118 return 0; 119 120 l4re_util_cap_free(cap); 121 122 /* Do the unmapping separately since the capability may not actually be 123 managed by the capability allocator if, for example, obtained from the 124 environment. */ 125 126 l4_task_unmap(L4RE_THIS_TASK_CAP, l4_obj_fpage(cap, 0, L4_CAP_FPAGE_RWSD), 127 L4_FP_ALL_SPACES); 128 129 ipc_semaphore_up(ipc_cap_alloc_semaphore); 130 131 return 1; 132 } 133 134 // vim: tabstop=2 expandtab shiftwidth=2