Changeset c47e1a8 in mainline for uspace/lib/c/generic
- Timestamp:
- 2010-05-21T07:50:04Z (16 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- d51ee2b
- Parents:
- cf8cc36 (diff), 15b592b (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- uspace/lib/c/generic
- Files:
-
- 4 added
- 46 moved
-
adt/hash_table.c (moved) (moved from uspace/lib/libc/generic/adt/hash_table.c ) (11 diffs)
-
adt/list.c (moved) (moved from uspace/lib/libc/generic/adt/list.c )
-
arg_parse.c (added)
-
as.c (moved) (moved from uspace/lib/libc/generic/as.c )
-
async.c (moved) (moved from uspace/lib/libc/generic/async.c ) (11 diffs)
-
cap.c (moved) (moved from uspace/lib/libc/generic/cap.c )
-
clipboard.c (moved) (moved from uspace/lib/libc/generic/clipboard.c ) (2 diffs)
-
ddi.c (moved) (moved from uspace/lib/libc/generic/ddi.c )
-
device/char.c (moved) (moved from uspace/lib/libc/generic/device/char.c ) (2 diffs)
-
device/hw_res.c (moved) (moved from uspace/lib/libc/generic/device/hw_res.c )
-
devman.c (moved) (moved from uspace/lib/libc/generic/devman.c ) (1 diff)
-
devmap.c (moved) (moved from uspace/lib/libc/generic/devmap.c ) (1 diff)
-
err.c (moved) (moved from uspace/lib/libc/generic/err.c )
-
errno.c (moved) (moved from uspace/lib/libc/generic/errno.c )
-
event.c (moved) (moved from uspace/lib/libc/generic/event.c )
-
fibril.c (moved) (moved from uspace/lib/libc/generic/fibril.c ) (15 diffs)
-
fibril_synch.c (moved) (moved from uspace/lib/libc/generic/fibril_synch.c )
-
futex.c (moved) (moved from uspace/lib/libc/generic/futex.c ) (5 diffs)
-
getopt.c (moved) (moved from uspace/lib/libc/generic/getopt.c ) (1 diff)
-
io/asprintf.c (moved) (moved from uspace/lib/libc/generic/io/asprintf.c ) (2 diffs)
-
io/console.c (moved) (moved from uspace/lib/libc/generic/io/console.c ) (3 diffs)
-
io/io.c (moved) (moved from uspace/lib/libc/generic/io/io.c ) (20 diffs)
-
io/klog.c (moved) (moved from uspace/lib/libc/generic/io/klog.c ) (1 diff)
-
io/printf.c (moved) (moved from uspace/lib/libc/generic/io/printf.c )
-
io/printf_core.c (moved) (moved from uspace/lib/libc/generic/io/printf_core.c ) (10 diffs)
-
io/screenbuffer.c (moved) (moved from uspace/srv/hid/console/screenbuffer.c ) (6 diffs)
-
io/snprintf.c (moved) (moved from uspace/lib/libc/generic/io/snprintf.c )
-
io/vprintf.c (moved) (moved from uspace/lib/libc/generic/io/vprintf.c ) (2 diffs)
-
io/vsnprintf.c (moved) (moved from uspace/lib/libc/generic/io/vsnprintf.c ) (1 diff)
-
ipc.c (moved) (moved from uspace/lib/libc/generic/ipc.c ) (1 diff)
-
libc.c (moved) (moved from uspace/lib/libc/generic/libc.c ) (3 diffs)
-
loader.c (moved) (moved from uspace/lib/libc/generic/loader.c ) (3 diffs)
-
malloc.c (moved) (moved from uspace/lib/libc/generic/malloc.c ) (19 diffs)
-
mem.c (moved) (moved from uspace/lib/libc/generic/mem.c )
-
mman.c (moved) (moved from uspace/lib/libc/generic/mman.c ) (1 diff)
-
pcb.c (moved) (moved from uspace/lib/libc/generic/pcb.c )
-
smc.c (moved) (moved from uspace/lib/libc/generic/smc.c )
-
stacktrace.c (moved) (moved from uspace/lib/libc/generic/stacktrace.c )
-
stats.c (added)
-
stdlib.c (moved) (moved from uspace/lib/libc/generic/stdlib.c )
-
str.c (moved) (moved from uspace/lib/libc/generic/string.c ) (7 diffs)
-
str_error.c (added)
-
sysinfo.c (added)
-
task.c (moved) (moved from uspace/lib/libc/generic/task.c ) (4 diffs)
-
thread.c (moved) (moved from uspace/lib/libc/generic/thread.c ) (2 diffs)
-
time.c (moved) (moved from uspace/lib/libc/generic/time.c )
-
tls.c (moved) (moved from uspace/lib/libc/generic/tls.c ) (1 diff)
-
udebug.c (moved) (moved from uspace/lib/libc/generic/udebug.c )
-
vfs/canonify.c (moved) (moved from uspace/lib/libc/generic/vfs/canonify.c )
-
vfs/vfs.c (moved) (moved from uspace/lib/libc/generic/vfs/vfs.c ) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/adt/hash_table.c
rcf8cc36 rc47e1a8 42 42 #include <malloc.h> 43 43 #include <assert.h> 44 #include <stdio.h> 45 #include <string.h> 44 #include <str.h> 46 45 47 46 /** Create chained hash table. 48 47 * 49 * @param h Hash table structure. Will be initialized by this call. 50 * @param m Number of hash table buckets. 51 * @param max_keys Maximal number of keys needed to identify an item. 52 * @param op Hash table operations structure. 53 * @return True on success 48 * @param h Hash table structure. Will be initialized by this call. 49 * @param m Number of hash table buckets. 50 * @param max_keys Maximal number of keys needed to identify an item. 51 * @param op Hash table operations structure. 52 * 53 * @return True on success 54 * 54 55 */ 55 56 int hash_table_create(hash_table_t *h, hash_count_t m, hash_count_t max_keys, 56 57 hash_table_operations_t *op) 57 58 { 58 hash_count_t i;59 60 59 assert(h); 61 60 assert(op && op->hash && op->compare); … … 63 62 64 63 h->entry = malloc(m * sizeof(link_t)); 65 if (!h->entry) { 66 printf("cannot allocate memory for hash table\n"); 64 if (!h->entry) 67 65 return false; 68 }66 69 67 memset((void *) h->entry, 0, m * sizeof(link_t)); 70 68 69 hash_count_t i; 71 70 for (i = 0; i < m; i++) 72 71 list_initialize(&h->entry[i]); … … 75 74 h->max_keys = max_keys; 76 75 h->op = op; 76 77 77 return true; 78 78 } … … 80 80 /** Destroy a hash table instance. 81 81 * 82 * @param h Hash table to be destroyed. 82 * @param h Hash table to be destroyed. 83 * 83 84 */ 84 85 void hash_table_destroy(hash_table_t *h) … … 86 87 assert(h); 87 88 assert(h->entry); 89 88 90 free(h->entry); 89 91 } … … 91 93 /** Insert item into a hash table. 92 94 * 93 * @param h Hash table.94 * @param key Array of all keys necessary to compute hash index.95 * @param item Item to be inserted into the hash table.95 * @param h Hash table. 96 * @param key Array of all keys necessary to compute hash index. 97 * @param item Item to be inserted into the hash table. 96 98 */ 97 99 void hash_table_insert(hash_table_t *h, unsigned long key[], link_t *item) 98 100 { 99 hash_index_t chain;100 101 101 assert(item); 102 102 assert(h && h->op && h->op->hash && h->op->compare); 103 104 chain = h->op->hash(key);103 104 hash_index_t chain = h->op->hash(key); 105 105 assert(chain < h->entries); 106 106 … … 110 110 /** Search hash table for an item matching keys. 111 111 * 112 * @param h Hash table. 113 * @param key Array of all keys needed to compute hash index. 114 * 115 * @return Matching item on success, NULL if there is no such item. 112 * @param h Hash table. 113 * @param key Array of all keys needed to compute hash index. 114 * 115 * @return Matching item on success, NULL if there is no such item. 116 * 116 117 */ 117 118 link_t *hash_table_find(hash_table_t *h, unsigned long key[]) 118 119 { 120 assert(h && h->op && h->op->hash && h->op->compare); 121 122 hash_index_t chain = h->op->hash(key); 123 assert(chain < h->entries); 124 119 125 link_t *cur; 120 hash_index_t chain;121 122 assert(h && h->op && h->op->hash && h->op->compare);123 124 chain = h->op->hash(key);125 assert(chain < h->entries);126 127 126 for (cur = h->entry[chain].next; cur != &h->entry[chain]; 128 127 cur = cur->next) { … … 142 141 * For each removed item, h->remove_callback() is called. 143 142 * 144 * @param h Hash table. 145 * @param key Array of keys that will be compared against items of 146 * the hash table. 147 * @param keys Number of keys in the 'key' array. 143 * @param h Hash table. 144 * @param key Array of keys that will be compared against items of 145 * the hash table. 146 * @param keys Number of keys in the 'key' array. 147 * 148 148 */ 149 149 void hash_table_remove(hash_table_t *h, unsigned long key[], hash_count_t keys) 150 150 { 151 hash_index_t chain;152 link_t *cur;153 154 151 assert(h && h->op && h->op->hash && h->op->compare && 155 152 h->op->remove_callback); 156 153 assert(keys <= h->max_keys); 157 154 155 link_t *cur; 156 158 157 if (keys == h->max_keys) { 159 160 158 /* 161 159 * All keys are known, hash_table_find() can be used to find the 162 160 * entry. 163 161 */ 164 162 165 163 cur = hash_table_find(h, key); 166 164 if (cur) { … … 168 166 h->op->remove_callback(cur); 169 167 } 168 170 169 return; 171 170 } … … 175 174 * Any partially matching entries are to be removed. 176 175 */ 176 hash_index_t chain; 177 177 for (chain = 0; chain < h->entries; chain++) { 178 178 for (cur = h->entry[chain].next; cur != &h->entry[chain]; … … 195 195 /** Apply fucntion to all items in hash table. 196 196 * 197 * @param h Hash table.198 * @param f Function to be applied.199 * @param arg Argument to be passed to the function.200 * /201 void 202 hash_table_apply(hash_table_t *h, void (*f)(link_t *, void *), void *arg)197 * @param h Hash table. 198 * @param f Function to be applied. 199 * @param arg Argument to be passed to the function. 200 * 201 */ 202 void hash_table_apply(hash_table_t *h, void (*f)(link_t *, void *), void *arg) 203 203 { 204 204 hash_index_t bucket; 205 205 link_t *cur; 206 206 207 207 for (bucket = 0; bucket < h->entries; bucket++) { 208 208 for (cur = h->entry[bucket].next; cur != &h->entry[bucket]; -
uspace/lib/c/generic/async.c
rcf8cc36 rc47e1a8 746 746 if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_CHAINS, 1, 747 747 &conn_hash_table_ops)) { 748 printf("%s: cannot create hash table\n", "async");748 printf("%s: Cannot create async hash table\n", "libc"); 749 749 return ENOMEM; 750 750 } … … 1101 1101 } 1102 1102 1103 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework. 1104 * 1105 * Ask through phone for a new connection to some service. 1106 * 1107 * @param phoneid Phone handle used for contacting the other side. 1108 * @param arg1 User defined argument. 1109 * @param arg2 User defined argument. 1110 * @param arg3 User defined argument. 1111 * 1112 * @return New phone handle on success or a negative error code. 1113 */ 1114 int 1115 async_connect_me_to(int phoneid, ipcarg_t arg1, ipcarg_t arg2, ipcarg_t arg3) 1116 { 1117 int rc; 1118 ipcarg_t newphid; 1119 1120 rc = async_req_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, NULL, 1121 NULL, NULL, NULL, &newphid); 1122 1123 if (rc != EOK) 1124 return rc; 1125 1126 return newphid; 1127 } 1128 1129 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework. 1130 * 1131 * Ask through phone for a new connection to some service and block until 1132 * success. 1133 * 1134 * @param phoneid Phone handle used for contacting the other side. 1135 * @param arg1 User defined argument. 1136 * @param arg2 User defined argument. 1137 * @param arg3 User defined argument. 1138 * 1139 * @return New phone handle on success or a negative error code. 1140 */ 1141 int 1142 async_connect_me_to_blocking(int phoneid, ipcarg_t arg1, ipcarg_t arg2, 1143 ipcarg_t arg3) 1144 { 1145 int rc; 1146 ipcarg_t newphid; 1147 1148 rc = async_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 1149 IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid); 1150 1151 if (rc != EOK) 1152 return rc; 1153 1154 return newphid; 1155 } 1156 1103 1157 /** Wrapper for making IPC_M_SHARE_IN calls using the async framework. 1104 1158 * … … 1310 1364 IPC_FF_ROUTE_FROM_ME); 1311 1365 if (retval != EOK) { 1366 async_wait_for(msg, NULL); 1312 1367 ipc_answer_0(callid, retval); 1313 1368 return retval; … … 1383 1438 } 1384 1439 1385 /** Wrapper for receiving binary data 1440 /** Wrapper for receiving binary data or strings 1386 1441 * 1387 1442 * This wrapper only makes it more comfortable to use async_data_write_* 1388 * functions to receive binary data .1443 * functions to receive binary data or strings. 1389 1444 * 1390 1445 * @param data Pointer to data pointer (which should be later disposed 1391 1446 * by free()). If the operation fails, the pointer is not 1392 1447 * touched. 1448 * @param nullterm If true then the received data is always zero terminated. 1449 * This also causes to allocate one extra byte beyond the 1450 * raw transmitted data. 1393 1451 * @param min_size Minimum size (in bytes) of the data to receive. 1394 1452 * @param max_size Maximum size (in bytes) of the data to receive. 0 means 1395 1453 * no limit. 1396 * @param granulariy If non-zero ,then the size of the received data has to1454 * @param granulariy If non-zero then the size of the received data has to 1397 1455 * be divisible by this value. 1398 1456 * @param received If not NULL, the size of the received data is stored here. … … 1401 1459 * 1402 1460 */ 1403 int async_data_receive(void **data, const size_t min_size, 1404 const size_t max_size, const size_t granularity, size_t *received) 1461 int async_data_write_accept(void **data, const bool nullterm, 1462 const size_t min_size, const size_t max_size, const size_t granularity, 1463 size_t *received) 1405 1464 { 1406 1465 ipc_callid_t callid; … … 1426 1485 } 1427 1486 1428 void *_data = malloc(size); 1487 void *_data; 1488 1489 if (nullterm) 1490 _data = malloc(size + 1); 1491 else 1492 _data = malloc(size); 1493 1429 1494 if (_data == NULL) { 1430 1495 ipc_answer_0(callid, ENOMEM); … … 1438 1503 } 1439 1504 1505 if (nullterm) 1506 ((char *) _data)[size] = 0; 1507 1440 1508 *data = _data; 1441 1509 if (received != NULL) … … 1445 1513 } 1446 1514 1447 /** Wrapper for receiving strings1448 *1449 * This wrapper only makes it more comfortable to use async_data_write_*1450 * functions to receive strings.1451 *1452 * @param str Pointer to string pointer (which should be later disposed1453 * by free()). If the operation fails, the pointer is not1454 * touched.1455 * @param max_size Maximum size (in bytes) of the string to receive. 0 means1456 * no limit.1457 * @param received If not NULL, the size of the received data is stored here.1458 *1459 * @return Zero on success or a value from @ref errno.h on failure.1460 *1461 */1462 int async_string_receive(char **str, const size_t max_size, size_t *received)1463 {1464 ipc_callid_t callid;1465 size_t size;1466 if (!async_data_write_receive(&callid, &size)) {1467 ipc_answer_0(callid, EINVAL);1468 return EINVAL;1469 }1470 1471 if ((max_size > 0) && (size > max_size)) {1472 ipc_answer_0(callid, EINVAL);1473 return EINVAL;1474 }1475 1476 char *data = (char *) malloc(size + 1);1477 if (data == NULL) {1478 ipc_answer_0(callid, ENOMEM);1479 return ENOMEM;1480 }1481 1482 int rc = async_data_write_finalize(callid, data, size);1483 if (rc != EOK) {1484 free(data);1485 return rc;1486 }1487 1488 data[size] = 0;1489 *str = data;1490 if (received != NULL)1491 *received = size;1492 1493 return EOK;1494 }1495 1496 1515 /** Wrapper for voiding any data that is about to be received 1497 1516 * … … 1501 1520 * 1502 1521 */ 1503 void async_data_ void(const int retval)1522 void async_data_write_void(const int retval) 1504 1523 { 1505 1524 ipc_callid_t callid; … … 1512 1531 * 1513 1532 */ 1514 int async_data_ forward_fast(int phoneid, ipcarg_t method, ipcarg_t arg1,1533 int async_data_write_forward_fast(int phoneid, ipcarg_t method, ipcarg_t arg1, 1515 1534 ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr) 1516 1535 { … … 1531 1550 IPC_FF_ROUTE_FROM_ME); 1532 1551 if (retval != EOK) { 1552 async_wait_for(msg, NULL); 1533 1553 ipc_answer_0(callid, retval); 1534 1554 return retval; -
uspace/lib/c/generic/clipboard.c
rcf8cc36 rc47e1a8 42 42 #include <ipc/clipboard.h> 43 43 #include <async.h> 44 #include <str ing.h>44 #include <str.h> 45 45 #include <errno.h> 46 46 #include <malloc.h> … … 148 148 aid_t req = async_send_1(clip_phone, CLIPBOARD_GET_DATA, tag, NULL); 149 149 rc = async_data_read_start(clip_phone, (void *) sbuf, size); 150 if ( rc == EOVERFLOW) {150 if ((int) rc == EOVERFLOW) { 151 151 /* 152 152 * The data in the clipboard has changed since -
uspace/lib/c/generic/device/char.c
rcf8cc36 rc47e1a8 60 60 61 61 aid_t req; 62 int r c;62 int ret; 63 63 64 64 if (read) { 65 65 req = async_send_1(dev_phone, DEV_IFACE_ID(CHAR_DEV_IFACE), CHAR_READ_DEV, &answer); 66 r c= async_data_read_start(dev_phone, buf, len);66 ret = async_data_read_start(dev_phone, buf, len); 67 67 } else { 68 68 req = async_send_1(dev_phone, DEV_IFACE_ID(CHAR_DEV_IFACE), CHAR_WRITE_DEV, &answer); 69 r c= async_data_write_start(dev_phone, buf, len);69 ret = async_data_write_start(dev_phone, buf, len); 70 70 } 71 71 72 i f (rc != EOK) {73 ipcarg_t rc_orig;74 async_wait_for(req, &rc _orig);72 ipcarg_t rc; 73 if (ret != EOK) { 74 async_wait_for(req, &rc); 75 75 async_serialize_end(); 76 if (rc _orig== EOK) {77 return r c;76 if (rc == EOK) { 77 return ret; 78 78 } 79 79 else { 80 return (int) rc _orig;80 return (int) rc; 81 81 } 82 82 } … … 85 85 async_serialize_end(); 86 86 87 if (EOK != rc) { 88 return rc; 87 ret = (int)rc; 88 if (EOK != ret) { 89 return ret; 89 90 } 90 91 -
uspace/lib/c/generic/devman.c
rcf8cc36 rc47e1a8 35 35 */ 36 36 37 #include <str ing.h>37 #include <str.h> 38 38 #include <stdio.h> 39 39 #include <ipc/ipc.h> -
uspace/lib/c/generic/devmap.c
rcf8cc36 rc47e1a8 28 28 */ 29 29 30 #include <str ing.h>30 #include <str.h> 31 31 #include <ipc/ipc.h> 32 32 #include <ipc/services.h> -
uspace/lib/c/generic/fibril.c
rcf8cc36 rc47e1a8 41 41 #include <unistd.h> 42 42 #include <stdio.h> 43 #include <arch/barrier.h> 43 44 #include <libarch/faddr.h> 44 45 #include <futex.h> … … 47 48 48 49 #ifndef FIBRIL_INITIAL_STACK_PAGES_NO 49 #define FIBRIL_INITIAL_STACK_PAGES_NO150 #define FIBRIL_INITIAL_STACK_PAGES_NO 1 50 51 #endif 51 52 52 53 /** 53 * This futex serializes access to ready_list, serialized_list and manager_list. 54 */ 54 * This futex serializes access to ready_list, 55 * serialized_list and manager_list. 56 */ 55 57 static atomic_t fibril_futex = FUTEX_INITIALIZER; 56 58 … … 59 61 static LIST_INITIALIZE(manager_list); 60 62 61 static void fibril_main(void);62 63 63 /** Number of threads that are executing a manager fibril. */ 64 64 static int threads_in_manager; 65 /** Number of threads that are executing a manager fibril and are serialized. */ 66 static int serialized_threads; /* Protected by async_futex */ 65 66 /** 67 * Number of threads that are executing a manager fibril 68 * and are serialized. Protected by async_futex. 69 */ 70 static int serialized_threads; 71 67 72 /** Fibril-local count of serialization. If > 0, we must not preempt */ 68 73 static fibril_local int serialization_count; 69 70 /** Setup fibril information into TCB structure */71 fibril_t *fibril_setup(void)72 {73 fibril_t *f;74 tcb_t *tcb;75 76 tcb = __make_tls();77 if (!tcb)78 return NULL;79 80 f = malloc(sizeof(fibril_t));81 if (!f) {82 __free_tls(tcb);83 return NULL;84 }85 86 tcb->fibril_data = f;87 f->tcb = tcb;88 89 f->func = NULL;90 f->arg = NULL;91 f->stack = NULL;92 f->clean_after_me = NULL;93 f->retval = 0;94 f->flags = 0;95 96 return f;97 }98 99 void fibril_teardown(fibril_t *f)100 {101 __free_tls(f->tcb);102 free(f);103 }104 74 105 75 /** Function that spans the whole life-cycle of a fibril. … … 108 78 * the fibril logic is called. After its return, the return value is saved. 109 79 * The fibril then switches to another fibril, which cleans up after it. 110 */ 111 void fibril_main(void) 112 { 113 fibril_t *f = __tcb_get()->fibril_data; 114 80 * 81 */ 82 static void fibril_main(void) 83 { 84 fibril_t *fibril = __tcb_get()->fibril_data; 85 115 86 /* Call the implementing function. */ 116 f ->retval = f->func(f->arg);117 87 fibril->retval = fibril->func(fibril->arg); 88 118 89 fibril_switch(FIBRIL_FROM_DEAD); 119 /* not reached */ 90 /* Not reached */ 91 } 92 93 /** Setup fibril information into TCB structure 94 * 95 */ 96 fibril_t *fibril_setup(void) 97 { 98 tcb_t *tcb = __make_tls(); 99 if (!tcb) 100 return NULL; 101 102 fibril_t *fibril = malloc(sizeof(fibril_t)); 103 if (!fibril) { 104 __free_tls(tcb); 105 return NULL; 106 } 107 108 tcb->fibril_data = fibril; 109 fibril->tcb = tcb; 110 111 fibril->func = NULL; 112 fibril->arg = NULL; 113 fibril->stack = NULL; 114 fibril->clean_after_me = NULL; 115 fibril->retval = 0; 116 fibril->flags = 0; 117 118 return fibril; 119 } 120 121 void fibril_teardown(fibril_t *fibril) 122 { 123 __free_tls(fibril->tcb); 124 free(fibril); 120 125 } 121 126 … … 125 130 * held. 126 131 * 127 * @param stype Switch type. One of FIBRIL_PREEMPT, FIBRIL_TO_MANAGER, 128 * FIBRIL_FROM_MANAGER, FIBRIL_FROM_DEAD. The parameter 129 * describes the circumstances of the switch. 130 * @return Return 0 if there is no ready fibril, 131 * return 1 otherwise. 132 * @param stype Switch type. One of FIBRIL_PREEMPT, FIBRIL_TO_MANAGER, 133 * FIBRIL_FROM_MANAGER, FIBRIL_FROM_DEAD. The parameter 134 * describes the circumstances of the switch. 135 * 136 * @return 0 if there is no ready fibril, 137 * @return 1 otherwise. 138 * 132 139 */ 133 140 int fibril_switch(fibril_switch_type_t stype) 134 141 { 135 fibril_t *srcf, *dstf;136 142 int retval = 0; 137 143 138 144 futex_down(&fibril_futex); 139 145 140 146 if (stype == FIBRIL_PREEMPT && list_empty(&ready_list)) 141 147 goto ret_0; 142 148 143 149 if (stype == FIBRIL_FROM_MANAGER) { 144 if ( list_empty(&ready_list) && list_empty(&serialized_list))150 if ((list_empty(&ready_list)) && (list_empty(&serialized_list))) 145 151 goto ret_0; 152 146 153 /* 147 154 * Do not preempt if there is not enough threads to run the 148 155 * ready fibrils which are not serialized. 149 156 */ 150 if ( list_empty(&serialized_list) &&151 threads_in_manager <= serialized_threads) {157 if ((list_empty(&serialized_list)) && 158 (threads_in_manager <= serialized_threads)) { 152 159 goto ret_0; 153 160 } 154 161 } 162 155 163 /* If we are going to manager and none exists, create it */ 156 if ( stype == FIBRIL_TO_MANAGER || stype == FIBRIL_FROM_DEAD) {164 if ((stype == FIBRIL_TO_MANAGER) || (stype == FIBRIL_FROM_DEAD)) { 157 165 while (list_empty(&manager_list)) { 158 166 futex_up(&fibril_futex); … … 162 170 } 163 171 164 srcf = __tcb_get()->fibril_data;172 fibril_t *srcf = __tcb_get()->fibril_data; 165 173 if (stype != FIBRIL_FROM_DEAD) { 174 166 175 /* Save current state */ 167 176 if (!context_save(&srcf->ctx)) { 168 177 if (serialization_count) 169 178 srcf->flags &= ~FIBRIL_SERIALIZED; 179 170 180 if (srcf->clean_after_me) { 171 181 /* … … 173 183 * restored context here. 174 184 */ 175 void *stack = srcf->clean_after_me->stack; 185 void *stack = srcf->clean_after_me->stack; 176 186 if (stack) { 177 187 /* … … 188 198 srcf->clean_after_me = NULL; 189 199 } 200 190 201 return 1; /* futex_up already done here */ 191 202 } 192 203 193 204 /* Save myself to the correct run list */ 194 205 if (stype == FIBRIL_PREEMPT) … … 197 208 list_append(&srcf->link, &manager_list); 198 209 threads_in_manager--; 199 } else { 210 } else { 200 211 /* 201 212 * If stype == FIBRIL_TO_MANAGER, don't put ourselves to … … 207 218 208 219 /* Choose a new fibril to run */ 209 if (stype == FIBRIL_TO_MANAGER || stype == FIBRIL_FROM_DEAD) { 220 fibril_t *dstf; 221 if ((stype == FIBRIL_TO_MANAGER) || (stype == FIBRIL_FROM_DEAD)) { 210 222 dstf = list_get_instance(manager_list.next, fibril_t, link); 211 223 if (serialization_count && stype == FIBRIL_TO_MANAGER) { … … 214 226 } 215 227 threads_in_manager++; 216 228 217 229 if (stype == FIBRIL_FROM_DEAD) 218 230 dstf->clean_after_me = srcf; … … 228 240 } 229 241 list_remove(&dstf->link); 230 242 231 243 futex_up(&fibril_futex); 232 244 context_restore(&dstf->ctx); 233 245 /* not reached */ 234 246 235 247 ret_0: 236 248 futex_up(&fibril_futex); … … 240 252 /** Create a new fibril. 241 253 * 242 * @param func Implementing function of the new fibril. 243 * @param arg Argument to pass to func. 244 * 245 * @return Return 0 on failure or TLS of the new fibril. 254 * @param func Implementing function of the new fibril. 255 * @param arg Argument to pass to func. 256 * 257 * @return 0 on failure or TLS of the new fibril. 258 * 246 259 */ 247 260 fid_t fibril_create(int (*func)(void *), void *arg) 248 261 { 249 fibril_t *f ;250 251 f = fibril_setup();252 if ( !f)262 fibril_t *fibril; 263 264 fibril = fibril_setup(); 265 if (fibril == NULL) 253 266 return 0; 254 f->stack = (char *) malloc(FIBRIL_INITIAL_STACK_PAGES_NO * 255 getpagesize()); 256 if (!f->stack) { 257 fibril_teardown(f); 267 268 fibril->stack = 269 (char *) malloc(FIBRIL_INITIAL_STACK_PAGES_NO * getpagesize()); 270 if (!fibril->stack) { 271 fibril_teardown(fibril); 258 272 return 0; 259 273 } 260 274 261 f ->func = func;262 f ->arg = arg;263 264 context_save(&f ->ctx);265 context_set(&f ->ctx, FADDR(fibril_main), f->stack,266 FIBRIL_INITIAL_STACK_PAGES_NO * getpagesize(), f ->tcb);267 268 return (fid_t) f ;275 fibril->func = func; 276 fibril->arg = arg; 277 278 context_save(&fibril->ctx); 279 context_set(&fibril->ctx, FADDR(fibril_main), fibril->stack, 280 FIBRIL_INITIAL_STACK_PAGES_NO * getpagesize(), fibril->tcb); 281 282 return (fid_t) fibril; 269 283 } 270 284 271 285 /** Add a fibril to the ready list. 272 286 * 273 * @param fid Pointer to the fibril structure of the fibril to be 274 * added. 287 * @param fid Pointer to the fibril structure of the fibril to be 288 * added. 289 * 275 290 */ 276 291 void fibril_add_ready(fid_t fid) 277 292 { 278 fibril_t *f; 279 280 f = (fibril_t *) fid; 293 fibril_t *fibril = (fibril_t *) fid; 294 281 295 futex_down(&fibril_futex); 282 if ((f->flags & FIBRIL_SERIALIZED)) 283 list_append(&f->link, &serialized_list); 296 297 if ((fibril->flags & FIBRIL_SERIALIZED)) 298 list_append(&fibril->link, &serialized_list); 284 299 else 285 list_append(&f->link, &ready_list); 300 list_append(&fibril->link, &ready_list); 301 286 302 futex_up(&fibril_futex); 287 303 } … … 289 305 /** Add a fibril to the manager list. 290 306 * 291 * @param fid Pointer to the fibril structure of the fibril to be 292 * added. 307 * @param fid Pointer to the fibril structure of the fibril to be 308 * added. 309 * 293 310 */ 294 311 void fibril_add_manager(fid_t fid) 295 312 { 296 fibril_t *f; 297 298 f = (fibril_t *) fid; 299 313 fibril_t *fibril = (fibril_t *) fid; 314 300 315 futex_down(&fibril_futex); 301 list_append(&f ->link, &manager_list);316 list_append(&fibril->link, &manager_list); 302 317 futex_up(&fibril_futex); 303 318 } … … 307 322 { 308 323 futex_down(&fibril_futex); 309 if (list_empty(&manager_list)) { 310 futex_up(&fibril_futex); 311 return; 312 } 313 list_remove(manager_list.next); 324 325 if (!list_empty(&manager_list)) 326 list_remove(manager_list.next); 327 314 328 futex_up(&fibril_futex); 315 329 } -
uspace/lib/c/generic/futex.c
rcf8cc36 rc47e1a8 31 31 */ 32 32 /** @file 33 */ 33 */ 34 34 35 35 #include <futex.h> … … 40 40 /** Initialize futex counter. 41 41 * 42 * @param futex Futex. 43 * @param val Initialization value. 42 * @param futex Futex. 43 * @param val Initialization value. 44 * 44 45 */ 45 46 void futex_initialize(futex_t *futex, int val) … … 50 51 /** Try to down the futex. 51 52 * 52 * @param futex Futex. 53 * @return Non-zero if the futex was acquired. 54 * @return Zero if the futex was not acquired. 53 * @param futex Futex. 54 * 55 * @return Non-zero if the futex was acquired. 56 * @return Zero if the futex was not acquired. 57 * 55 58 */ 56 59 int futex_trydown(futex_t *futex) … … 61 64 /** Down the futex. 62 65 * 63 * @param futex Futex. 64 * @return ENOENT if there is no such virtual address. 65 * @return Zero in the uncontended case. 66 * @return Otherwise one of ESYNCH_OK_ATOMIC or ESYNCH_OK_BLOCKED. 66 * @param futex Futex. 67 * 68 * @return ENOENT if there is no such virtual address. 69 * @return Zero in the uncontended case. 70 * @return Otherwise one of ESYNCH_OK_ATOMIC or ESYNCH_OK_BLOCKED. 71 * 67 72 */ 68 73 int futex_down(futex_t *futex) 69 74 { 70 if ( atomic_predec(futex) < 0)75 if ((atomic_signed_t) atomic_predec(futex) < 0) 71 76 return __SYSCALL1(SYS_FUTEX_SLEEP, (sysarg_t) &futex->count); 72 77 73 78 return 0; 74 79 } … … 76 81 /** Up the futex. 77 82 * 78 * @param futex Futex. 79 * @return ENOENT if there is no such virtual address. 80 * @return Zero in the uncontended case. 83 * @param futex Futex. 84 * 85 * @return ENOENT if there is no such virtual address. 86 * @return Zero in the uncontended case. 87 * 81 88 */ 82 89 int futex_up(futex_t *futex) 83 90 { 84 if ( atomic_postinc(futex) < 0)91 if ((atomic_signed_t) atomic_postinc(futex) < 0) 85 92 return __SYSCALL1(SYS_FUTEX_WAKEUP, (sysarg_t) &futex->count); 86 93 87 94 return 0; 88 95 } -
uspace/lib/c/generic/getopt.c
rcf8cc36 rc47e1a8 38 38 #include <getopt.h> 39 39 #include <stdlib.h> 40 #include <str ing.h>40 #include <str.h> 41 41 42 42 /* HelenOS Port : We're incorporating only the modern getopt_long with wrappers -
uspace/lib/c/generic/io/asprintf.c
rcf8cc36 rc47e1a8 37 37 #include <stdio.h> 38 38 #include <stdlib.h> 39 #include <str ing.h>39 #include <str.h> 40 40 #include <io/printf_core.h> 41 41 … … 61 61 int asprintf(char **strp, const char *fmt, ...) 62 62 { 63 struct printf_specps = {63 printf_spec_t ps = { 64 64 asprintf_str_write, 65 65 asprintf_wstr_write, -
uspace/lib/c/generic/io/console.c
rcf8cc36 rc47e1a8 45 45 } 46 46 47 int console_get_size(int phone, i nt *cols, int *rows)47 int console_get_size(int phone, ipcarg_t *cols, ipcarg_t *rows) 48 48 { 49 ipcarg_t cols_v; 50 ipcarg_t rows_v; 51 int rc; 52 53 rc = async_req_0_2(phone, CONSOLE_GET_SIZE, &cols_v, &rows_v); 54 55 *cols = (int) cols_v; 56 *rows = (int) rows_v; 57 return rc; 49 return async_req_0_2(phone, CONSOLE_GET_SIZE, cols, rows); 58 50 } 59 51 60 void console_set_style(int phone, int style)52 void console_set_style(int phone, uint8_t style) 61 53 { 62 54 async_msg_1(phone, CONSOLE_SET_STYLE, style); 63 55 } 64 56 65 void console_set_color(int phone, int fg_color, int bg_color, int flags) 57 void console_set_color(int phone, uint8_t fg_color, uint8_t bg_color, 58 uint8_t flags) 66 59 { 67 60 async_msg_3(phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags); 68 61 } 69 62 70 void console_set_rgb_color(int phone, int fg_color, int bg_color)63 void console_set_rgb_color(int phone, uint32_t fg_color, uint32_t bg_color) 71 64 { 72 65 async_msg_2(phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color); … … 75 68 void console_cursor_visibility(int phone, bool show) 76 69 { 77 async_msg_1(phone, CONSOLE_CURSOR_VISIBILITY, show != false);70 async_msg_1(phone, CONSOLE_CURSOR_VISIBILITY, (show != false)); 78 71 } 79 72 80 int console_get_color_cap(int phone, i nt *ccap)73 int console_get_color_cap(int phone, ipcarg_t *ccap) 81 74 { 82 ipcarg_t ccap_tmp; 83 int rc; 84 85 rc = async_req_0_1(phone, CONSOLE_GET_COLOR_CAP, &ccap_tmp); 86 *ccap = ccap_tmp; 87 88 return rc; 75 return async_req_0_1(phone, CONSOLE_GET_COLOR_CAP, ccap); 89 76 } 90 77 … … 94 81 } 95 82 96 int console_get_pos(int phone, i nt *col, int *row)83 int console_get_pos(int phone, ipcarg_t *col, ipcarg_t *row) 97 84 { 98 ipcarg_t col_v; 99 ipcarg_t row_v; 100 int rc; 101 102 rc = async_req_0_2(phone, CONSOLE_GET_POS, &col_v, &row_v); 103 104 *col = (int) col_v; 105 *row = (int) row_v; 106 return rc; 85 return async_req_0_2(phone, CONSOLE_GET_POS, col, row); 107 86 } 108 87 109 void console_ goto(int phone, int col, int row)88 void console_set_pos(int phone, ipcarg_t col, ipcarg_t row) 110 89 { 111 90 async_msg_2(phone, CONSOLE_GOTO, col, row); -
uspace/lib/c/generic/io/io.c
rcf8cc36 rc47e1a8 37 37 #include <fcntl.h> 38 38 #include <assert.h> 39 #include <str ing.h>39 #include <str.h> 40 40 #include <errno.h> 41 41 #include <bool.h> … … 46 46 #include <adt/list.h> 47 47 48 static void _ffillbuf(FILE *stream); 48 49 static void _fflushbuf(FILE *stream); 49 50 … … 57 58 .buf = NULL, 58 59 .buf_size = 0, 59 .buf_head = NULL 60 .buf_head = NULL, 61 .buf_tail = NULL, 62 .buf_state = _bs_empty 60 63 }; 61 64 … … 69 72 .buf = NULL, 70 73 .buf_size = BUFSIZ, 71 .buf_head = NULL 74 .buf_head = NULL, 75 .buf_tail = NULL, 76 .buf_state = _bs_empty 72 77 }; 73 78 … … 81 86 .buf = NULL, 82 87 .buf_size = 0, 83 .buf_head = NULL 88 .buf_head = NULL, 89 .buf_tail = NULL, 90 .buf_state = _bs_empty 84 91 }; 85 92 … … 179 186 stream->buf_size = size; 180 187 stream->buf_head = stream->buf; 188 stream->buf_tail = stream->buf; 189 stream->buf_state = _bs_empty; 181 190 } 182 191 … … 210 219 211 220 stream->buf_head = stream->buf; 221 stream->buf_tail = stream->buf; 212 222 return 0; 213 223 } … … 243 253 stream->klog = false; 244 254 stream->phone = -1; 255 stream->need_sync = false; 245 256 _setvbuf(stream); 246 257 … … 264 275 stream->klog = false; 265 276 stream->phone = -1; 277 stream->need_sync = false; 266 278 _setvbuf(stream); 267 279 … … 295 307 stream->klog = false; 296 308 stream->phone = -1; 309 stream->need_sync = false; 297 310 _setvbuf(stream); 298 311 … … 331 344 } 332 345 333 /** Read from a stream .346 /** Read from a stream (unbuffered). 334 347 * 335 348 * @param buf Destination buffer. … … 337 350 * @param nmemb Number of records to read. 338 351 * @param stream Pointer to the stream. 339 * 340 */ 341 size_t fread(void *buf, size_t size, size_t nmemb, FILE *stream) 352 */ 353 static size_t _fread(void *buf, size_t size, size_t nmemb, FILE *stream) 342 354 { 343 355 size_t left, done; … … 345 357 if (size == 0 || nmemb == 0) 346 358 return 0; 347 348 /* Make sure no data is pending write. */349 _fflushbuf(stream);350 359 351 360 left = size * nmemb; … … 368 377 } 369 378 379 /** Write to a stream (unbuffered). 380 * 381 * @param buf Source buffer. 382 * @param size Size of each record. 383 * @param nmemb Number of records to write. 384 * @param stream Pointer to the stream. 385 */ 370 386 static size_t _fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream) 371 387 { … … 394 410 } 395 411 } 412 413 if (done > 0) 414 stream->need_sync = true; 396 415 397 416 return (done / size); 398 417 } 399 418 400 /** Drain stream buffer, do not sync stream. */ 419 /** Read some data in stream buffer. */ 420 static void _ffillbuf(FILE *stream) 421 { 422 ssize_t rc; 423 424 stream->buf_head = stream->buf_tail = stream->buf; 425 426 rc = read(stream->fd, stream->buf, stream->buf_size); 427 if (rc < 0) { 428 stream->error = true; 429 return; 430 } 431 432 if (rc == 0) { 433 stream->eof = true; 434 return; 435 } 436 437 stream->buf_head += rc; 438 stream->buf_state = _bs_read; 439 } 440 441 /** Write out stream buffer, do not sync stream. */ 401 442 static void _fflushbuf(FILE *stream) 402 443 { 403 444 size_t bytes_used; 404 445 405 446 if ((!stream->buf) || (stream->btype == _IONBF) || (stream->error)) 406 447 return; 407 408 bytes_used = stream->buf_head - stream->buf ;448 449 bytes_used = stream->buf_head - stream->buf_tail; 409 450 if (bytes_used == 0) 410 451 return; 411 412 (void) _fwrite(stream->buf, 1, bytes_used, stream); 452 453 /* If buffer has prefetched read data, we need to seek back. */ 454 if (stream->buf_state == _bs_read) 455 lseek(stream->fd, - (ssize_t) bytes_used, SEEK_CUR); 456 457 /* If buffer has unwritten data, we need to write them out. */ 458 if (stream->buf_state == _bs_write) 459 (void) _fwrite(stream->buf_tail, 1, bytes_used, stream); 460 413 461 stream->buf_head = stream->buf; 414 } 462 stream->buf_tail = stream->buf; 463 stream->buf_state = _bs_empty; 464 } 465 466 /** Read from a stream. 467 * 468 * @param dest Destination buffer. 469 * @param size Size of each record. 470 * @param nmemb Number of records to read. 471 * @param stream Pointer to the stream. 472 * 473 */ 474 size_t fread(void *dest, size_t size, size_t nmemb, FILE *stream) 475 { 476 uint8_t *dp; 477 size_t bytes_left; 478 size_t now; 479 size_t data_avail; 480 size_t total_read; 481 size_t i; 482 483 if (size == 0 || nmemb == 0) 484 return 0; 485 486 /* If not buffered stream, read in directly. */ 487 if (stream->btype == _IONBF) { 488 now = _fread(dest, size, nmemb, stream); 489 return now; 490 } 491 492 /* Make sure no data is pending write. */ 493 if (stream->buf_state == _bs_write) 494 _fflushbuf(stream); 495 496 /* Perform lazy allocation of stream buffer. */ 497 if (stream->buf == NULL) { 498 if (_fallocbuf(stream) != 0) 499 return 0; /* Errno set by _fallocbuf(). */ 500 } 501 502 bytes_left = size * nmemb; 503 total_read = 0; 504 dp = (uint8_t *) dest; 505 506 while ((!stream->error) && (!stream->eof) && (bytes_left > 0)) { 507 if (stream->buf_head == stream->buf_tail) 508 _ffillbuf(stream); 509 510 if (stream->error || stream->eof) 511 break; 512 513 data_avail = stream->buf_head - stream->buf_tail; 514 515 if (bytes_left > data_avail) 516 now = data_avail; 517 else 518 now = bytes_left; 519 520 for (i = 0; i < now; i++) { 521 dp[i] = stream->buf_tail[i]; 522 } 523 524 dp += now; 525 stream->buf_tail += now; 526 bytes_left -= now; 527 total_read += now; 528 } 529 530 return (total_read / size); 531 } 532 415 533 416 534 /** Write to a stream. … … 442 560 return now; 443 561 } 444 562 563 /* Make sure buffer contains no prefetched data. */ 564 if (stream->buf_state == _bs_read) 565 _fflushbuf(stream); 566 567 445 568 /* Perform lazy allocation of stream buffer. */ 446 569 if (stream->buf == NULL) { … … 482 605 } 483 606 607 if (total_written > 0) 608 stream->buf_state = _bs_write; 609 484 610 if (need_flush) 485 611 fflush(stream); … … 536 662 } 537 663 664 char *fgets(char *str, int size, FILE *stream) 665 { 666 int c; 667 int idx; 668 669 idx = 0; 670 while (idx < size - 1) { 671 c = fgetc(stream); 672 if (c == EOF) 673 break; 674 675 str[idx++] = c; 676 677 if (c == '\n') 678 break; 679 } 680 681 if (ferror(stream)) 682 return NULL; 683 684 if (idx == 0) 685 return NULL; 686 687 str[idx] = '\0'; 688 return str; 689 } 690 538 691 int getchar(void) 539 692 { … … 541 694 } 542 695 543 int fseek(FILE *stream, long offset, int origin) 544 { 545 off_t rc = lseek(stream->fd, offset, origin); 546 if (rc == (off_t) (-1)) { 547 /* errno has been set by lseek. */ 696 int fseek(FILE *stream, off64_t offset, int whence) 697 { 698 off64_t rc; 699 700 _fflushbuf(stream); 701 702 rc = lseek(stream->fd, offset, whence); 703 if (rc == (off64_t) (-1)) { 704 /* errno has been set by lseek64. */ 548 705 return -1; 549 706 } 550 707 551 708 stream->eof = false; 552 553 709 return 0; 554 710 } 555 711 556 int ftell(FILE *stream) 557 { 558 off_t rc = lseek(stream->fd, 0, SEEK_CUR); 559 if (rc == (off_t) (-1)) { 560 /* errno has been set by lseek. */ 561 return -1; 562 } 563 564 return rc; 712 off64_t ftell(FILE *stream) 713 { 714 return lseek(stream->fd, 0, SEEK_CUR); 565 715 } 566 716 … … 579 729 } 580 730 581 if (stream->fd >= 0) 731 if (stream->fd >= 0 && stream->need_sync) { 732 /** 733 * Better than syncing always, but probably still not the 734 * right thing to do. 735 */ 736 stream->need_sync = false; 582 737 return fsync(stream->fd); 738 } 583 739 584 740 return ENOENT; -
uspace/lib/c/generic/io/klog.c
rcf8cc36 rc47e1a8 35 35 36 36 #include <libc.h> 37 #include <str ing.h>37 #include <str.h> 38 38 #include <sys/types.h> 39 39 #include <unistd.h> -
uspace/lib/c/generic/io/printf_core.c
rcf8cc36 rc47e1a8 41 41 #include <io/printf_core.h> 42 42 #include <ctype.h> 43 #include <str ing.h>43 #include <str.h> 44 44 45 45 /** show prefixes 0x or 0 */ 46 46 #define __PRINTF_FLAG_PREFIX 0x00000001 47 47 48 /** signed / unsigned number */ 48 49 #define __PRINTF_FLAG_SIGNED 0x00000002 50 49 51 /** print leading zeroes */ 50 52 #define __PRINTF_FLAG_ZEROPADDED 0x00000004 53 51 54 /** align to left */ 52 55 #define __PRINTF_FLAG_LEFTALIGNED 0x00000010 56 53 57 /** always show + sign */ 54 58 #define __PRINTF_FLAG_SHOWPLUS 0x00000020 59 55 60 /** print space instead of plus */ 56 61 #define __PRINTF_FLAG_SPACESIGN 0x00000040 62 57 63 /** show big characters */ 58 64 #define __PRINTF_FLAG_BIGCHARS 0x00000080 65 59 66 /** number has - sign */ 60 67 #define __PRINTF_FLAG_NEGATIVE 0x00000100 … … 78 85 } qualifier_t; 79 86 80 static c har nullstr[]= "(NULL)";81 static c har digits_small[]= "0123456789abcdef";82 static c har digits_big[]= "0123456789ABCDEF";83 static c har invalch = U_SPECIAL;87 static const char *nullstr = "(NULL)"; 88 static const char *digits_small = "0123456789abcdef"; 89 static const char *digits_big = "0123456789ABCDEF"; 90 static const char invalch = U_SPECIAL; 84 91 85 92 /** Print one or more characters without adding newline. … … 253 260 if (str == NULL) 254 261 return printf_putstr(nullstr, ps); 255 262 256 263 /* Print leading spaces. */ 257 264 size_t strw = str_length(str); 258 265 if (precision == 0) 259 266 precision = strw; 260 267 261 268 /* Left padding */ 262 269 size_t counter = 0; … … 268 275 } 269 276 } 270 277 271 278 /* Part of @a str fitting into the alloted space. */ 272 279 int retval; … … 350 357 uint32_t flags, printf_spec_t *ps) 351 358 { 352 c har *digits;359 const char *digits; 353 360 if (flags & __PRINTF_FLAG_BIGCHARS) 354 361 digits = digits_big; … … 383 390 */ 384 391 if (flags & __PRINTF_FLAG_PREFIX) { 385 switch (base) {392 switch (base) { 386 393 case 2: 387 394 /* Binary formating is not standard, but usefull */ … … 447 454 /* Print prefix */ 448 455 if (flags & __PRINTF_FLAG_PREFIX) { 449 switch (base) {456 switch (base) { 450 457 case 2: 451 458 /* Binary formating is not standard, but usefull */ … … 562 569 * 563 570 * - P, p Print value of a pointer. Void * value is expected and it is 564 * printed in hexadecimal notation with prefix (as with \%#X / \%#x 565 * for 32-bit or \%#X / \%#x for 64-bit long pointers). 571 * printed in hexadecimal notation with prefix (as with 572 * \%#0.8X / \%#0.8x for 32-bit or \%#0.16lX / \%#0.16lx for 64-bit 573 * long pointers). 566 574 * 567 575 * - b Print value as unsigned binary number. Prefix is not printed by … … 776 784 case 'p': 777 785 flags |= __PRINTF_FLAG_PREFIX; 786 flags |= __PRINTF_FLAG_ZEROPADDED; 778 787 base = 16; 779 788 qualifier = PrintfQualifierPointer; … … 838 847 case PrintfQualifierPointer: 839 848 size = sizeof(void *); 840 number = (uint64_t) (unsigned long) va_arg(ap, void *); 849 precision = size << 1; 850 number = (uint64_t) (uintptr_t) va_arg(ap, void *); 841 851 break; 842 852 default: -
uspace/lib/c/generic/io/screenbuffer.c
rcf8cc36 rc47e1a8 34 34 35 35 #include <io/style.h> 36 #include <io/screenbuffer.h> 36 37 #include <malloc.h> 37 38 #include <unistd.h> 38 #include "screenbuffer.h"39 39 40 40 /** Store one character to screenbuffer. … … 67 67 * 68 68 */ 69 screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, size_t size_x, size_t size_y) 69 screenbuffer_t *screenbuffer_init(screenbuffer_t *scr, ipcarg_t size_x, 70 ipcarg_t size_y) 70 71 { 71 72 scr->buffer = (keyfield_t *) malloc(sizeof(keyfield_t) * size_x * size_y); … … 109 110 * 110 111 */ 111 void screenbuffer_clear_line(screenbuffer_t *scr, size_t line)112 void screenbuffer_clear_line(screenbuffer_t *scr, ipcarg_t line) 112 113 { 113 size_t x;114 ipcarg_t x; 114 115 115 116 for (x = 0; x < scr->size_x; x++) { … … 140 141 * 141 142 */ 142 void screenbuffer_goto(screenbuffer_t *scr, size_t x, size_t y)143 void screenbuffer_goto(screenbuffer_t *scr, ipcarg_t x, ipcarg_t y) 143 144 { 144 145 scr->position_x = x % scr->size_x; … … 166 167 * 167 168 */ 168 void screenbuffer_set_color(screenbuffer_t *scr, uint8_t fg_color, uint8_t bg_color, uint8_t flags) 169 void screenbuffer_set_color(screenbuffer_t *scr, uint8_t fg_color, 170 uint8_t bg_color, uint8_t flags) 169 171 { 170 172 scr->attrs.t = at_idx; … … 181 183 * 182 184 */ 183 void screenbuffer_set_rgb_color(screenbuffer_t *scr, uint32_t fg_color, uint32_t bg_color) 185 void screenbuffer_set_rgb_color(screenbuffer_t *scr, uint32_t fg_color, 186 uint32_t bg_color) 184 187 { 185 188 scr->attrs.t = at_rgb; -
uspace/lib/c/generic/io/vprintf.c
rcf8cc36 rc47e1a8 39 39 #include <futex.h> 40 40 #include <async.h> 41 #include <str ing.h>41 #include <str.h> 42 42 43 43 static atomic_t printf_futex = FUTEX_INITIALIZER; … … 76 76 int vfprintf(FILE *stream, const char *fmt, va_list ap) 77 77 { 78 struct printf_specps = {78 printf_spec_t ps = { 79 79 vprintf_str_write, 80 80 vprintf_wstr_write, -
uspace/lib/c/generic/io/vsnprintf.c
rcf8cc36 rc47e1a8 35 35 #include <stdarg.h> 36 36 #include <stdio.h> 37 #include <str ing.h>37 #include <str.h> 38 38 #include <io/printf_core.h> 39 39 #include <errno.h> -
uspace/lib/c/generic/ipc.c
rcf8cc36 rc47e1a8 728 728 int *flags) 729 729 { 730 int res; 731 sysarg_t tmp_flags; 732 res = ipc_call_sync_3_2(phoneid, IPC_M_SHARE_IN, (ipcarg_t) dst, 730 sysarg_t tmp_flags = 0; 731 int res = ipc_call_sync_3_2(phoneid, IPC_M_SHARE_IN, (ipcarg_t) dst, 733 732 (ipcarg_t) size, arg, NULL, &tmp_flags); 733 734 734 if (flags) 735 735 *flags = tmp_flags; 736 736 737 return res; 737 738 } -
uspace/lib/c/generic/libc.c
rcf8cc36 rc47e1a8 62 62 void __main(void *pcb_ptr) 63 63 { 64 int retval; 65 64 /* Initialize user task run-time environment */ 66 65 __heap_init(); 67 66 __async_init(); … … 75 74 char **argv; 76 75 76 /* Get command line arguments and initialize 77 standard input and output */ 77 78 if (__pcb == NULL) { 78 79 argc = 0; … … 86 87 } 87 88 88 retval = main(argc, argv); 89 90 __stdio_done(); 91 (void) task_retval(retval); 89 /* Run main() and set task return value 90 according the result */ 91 (void) task_retval(main(argc, argv)); 92 92 } 93 93 94 94 void __exit(void) 95 95 { 96 __stdio_done(); 96 97 fibril_teardown(__tcb_get()->fibril_data); 97 98 _exit(0); -
uspace/lib/c/generic/loader.c
rcf8cc36 rc47e1a8 38 38 #include <libc.h> 39 39 #include <task.h> 40 #include <str ing.h>40 #include <str.h> 41 41 #include <stdlib.h> 42 42 #include <async.h> … … 183 183 * 184 184 */ 185 int loader_set_args(loader_t *ldr, c har *const argv[])185 int loader_set_args(loader_t *ldr, const char *const argv[]) 186 186 { 187 187 /* … … 189 189 * compute size of the buffer needed. 190 190 */ 191 c har *const *ap = argv;191 const char *const *ap = argv; 192 192 size_t buffer_size = 0; 193 193 while (*ap != NULL) { -
uspace/lib/c/generic/malloc.c
rcf8cc36 rc47e1a8 43 43 #include <bitops.h> 44 44 #include <mem.h> 45 #include <futex.h> 45 46 #include <adt/gcdlcm.h> 46 47 … … 75 76 #define NET_SIZE(size) ((size) - STRUCT_OVERHEAD) 76 77 77 78 78 /** Header of a heap block 79 79 * … … 104 104 extern char _heap; 105 105 106 /** Futex for thread-safe heap manipulation */ 107 static futex_t malloc_futex = FUTEX_INITIALIZER; 108 106 109 /** Address of heap start */ 107 110 static void *heap_start = 0; … … 119 122 * 120 123 * Fills in the structures related to a heap block. 124 * Should be called only inside the critical section. 121 125 * 122 126 * @param addr Address of the block. … … 144 148 * Verifies that the structures related to a heap block still contain 145 149 * the magic constants. This helps detect heap corruption early on. 150 * Should be called only inside the critical section. 146 151 * 147 152 * @param addr Address of the block. … … 161 166 } 162 167 168 /** Increase the heap area size 169 * 170 * Should be called only inside the critical section. 171 * 172 * @param size Number of bytes to grow the heap by. 173 * 174 */ 163 175 static bool grow_heap(size_t size) 164 176 { 165 177 if (size == 0) 178 return false; 179 180 if ((heap_start + size < heap_start) || (heap_end + size < heap_end)) 166 181 return false; 167 182 … … 186 201 } 187 202 203 /** Decrease the heap area 204 * 205 * Should be called only inside the critical section. 206 * 207 * @param size Number of bytes to shrink the heap by. 208 * 209 */ 188 210 static void shrink_heap(void) 189 211 { … … 193 215 /** Initialize the heap allocator 194 216 * 195 * Find s how much physical memory we have and creates217 * Find how much physical memory we have and create 196 218 * the heap management structures that mark the whole 197 219 * physical memory as a single free block. … … 200 222 void __heap_init(void) 201 223 { 224 futex_down(&malloc_futex); 225 202 226 if (as_area_create((void *) &_heap, PAGE_SIZE, 203 227 AS_AREA_WRITE | AS_AREA_READ)) { … … 210 234 block_init(heap_start, heap_end - heap_start, true); 211 235 } 212 } 213 236 237 futex_up(&malloc_futex); 238 } 239 240 /** Get maximum heap address 241 * 242 */ 214 243 uintptr_t get_max_heap_addr(void) 215 244 { 245 futex_down(&malloc_futex); 246 216 247 if (max_heap_size == (size_t) -1) 217 248 max_heap_size = 218 249 max((size_t) (heap_end - heap_start), MAX_HEAP_SIZE); 219 250 220 return ((uintptr_t) heap_start + max_heap_size); 221 } 222 251 uintptr_t max_heap_addr = (uintptr_t) heap_start + max_heap_size; 252 253 futex_up(&malloc_futex); 254 255 return max_heap_addr; 256 } 257 258 /** Split heap block and mark it as used. 259 * 260 * Should be called only inside the critical section. 261 * 262 * @param cur Heap block to split. 263 * @param size Number of bytes to split and mark from the beginning 264 * of the block. 265 * 266 */ 223 267 static void split_mark(heap_block_head_t *cur, const size_t size) 224 268 { … … 240 284 241 285 /** Allocate a memory block 286 * 287 * Should be called only inside the critical section. 242 288 * 243 289 * @param size The size of the block to allocate. … … 353 399 } 354 400 401 /** Allocate memory by number of elements 402 * 403 * @param nmemb Number of members to allocate. 404 * @param size Size of one member in bytes. 405 * 406 * @return Allocated memory or NULL. 407 * 408 */ 355 409 void *calloc(const size_t nmemb, const size_t size) 356 410 { … … 358 412 if (block == NULL) 359 413 return NULL; 360 414 361 415 memset(block, 0, nmemb * size); 362 416 return block; 363 417 } 364 418 419 /** Allocate memory 420 * 421 * @param size Number of bytes to allocate. 422 * 423 * @return Allocated memory or NULL. 424 * 425 */ 365 426 void *malloc(const size_t size) 366 427 { 367 return malloc_internal(size, BASE_ALIGN); 368 } 369 428 futex_down(&malloc_futex); 429 void *block = malloc_internal(size, BASE_ALIGN); 430 futex_up(&malloc_futex); 431 432 return block; 433 } 434 435 /** Allocate memory with specified alignment 436 * 437 * @param align Alignment in byes. 438 * @param size Number of bytes to allocate. 439 * 440 * @return Allocated memory or NULL. 441 * 442 */ 370 443 void *memalign(const size_t align, const size_t size) 371 444 { … … 376 449 1 << (fnzb(max(sizeof(void *), align) - 1) + 1); 377 450 378 return malloc_internal(size, palign); 379 } 380 451 futex_down(&malloc_futex); 452 void *block = malloc_internal(size, palign); 453 futex_up(&malloc_futex); 454 455 return block; 456 } 457 458 /** Reallocate memory block 459 * 460 * @param addr Already allocated memory or NULL. 461 * @param size New size of the memory block. 462 * 463 * @return Reallocated memory or NULL. 464 * 465 */ 381 466 void *realloc(const void *addr, const size_t size) 382 467 { 383 468 if (addr == NULL) 384 469 return malloc(size); 470 471 futex_down(&malloc_futex); 385 472 386 473 /* Calculate the position of the header. */ … … 395 482 396 483 void *ptr = NULL; 484 bool reloc = false; 397 485 size_t real_size = GROSS_SIZE(ALIGN_UP(size, BASE_ALIGN)); 398 486 size_t orig_size = head->size; … … 412 500 } else { 413 501 /* Look at the next block. If it is free and the size is 414 sufficient then merge the two. */ 502 sufficient then merge the two. Otherwise just allocate 503 a new block, copy the original data into it and 504 free the original block. */ 415 505 heap_block_head_t *next_head = 416 506 (heap_block_head_t *) (((void *) head) + head->size); … … 424 514 425 515 ptr = ((void *) head) + sizeof(heap_block_head_t); 426 } else { 427 ptr = malloc(size); 428 if (ptr != NULL) { 429 memcpy(ptr, addr, NET_SIZE(orig_size)); 430 free(addr); 431 } 516 } else 517 reloc = true; 518 } 519 520 futex_up(&malloc_futex); 521 522 if (reloc) { 523 ptr = malloc(size); 524 if (ptr != NULL) { 525 memcpy(ptr, addr, NET_SIZE(orig_size)); 526 free(addr); 432 527 } 433 528 } … … 439 534 * 440 535 * @param addr The address of the block. 536 * 441 537 */ 442 538 void free(const void *addr) 443 539 { 540 futex_down(&malloc_futex); 541 444 542 /* Calculate the position of the header. */ 445 543 heap_block_head_t *head … … 480 578 481 579 shrink_heap(); 580 581 futex_up(&malloc_futex); 482 582 } 483 583 -
uspace/lib/c/generic/mman.c
rcf8cc36 rc47e1a8 39 39 40 40 void *mmap(void *start, size_t length, int prot, int flags, int fd, 41 off_t offset)41 aoff64_t offset) 42 42 { 43 43 if (!start) -
uspace/lib/c/generic/str.c
rcf8cc36 rc47e1a8 34 34 */ 35 35 36 #include <str ing.h>36 #include <str.h> 37 37 #include <stdlib.h> 38 38 #include <assert.h> … … 43 43 #include <align.h> 44 44 #include <mem.h> 45 #include <str ing.h>45 #include <str.h> 46 46 47 47 /** Byte mask consisting of lowest @n bits (out of 8) */ … … 471 471 * null-terminated and containing only complete characters. 472 472 * 473 * @param dest Destination buffer.473 * @param dest Destination buffer. 474 474 * @param count Size of the destination buffer (must be > 0). 475 475 * @param src Source string. … … 477 477 void str_cpy(char *dest, size_t size, const char *src) 478 478 { 479 wchar_t ch;480 size_t src_off;481 size_t dest_off;482 483 479 /* There must be space for a null terminator in the buffer. */ 484 480 assert(size > 0); 485 481 486 src_off = 0; 487 dest_off = 0; 488 482 size_t src_off = 0; 483 size_t dest_off = 0; 484 485 wchar_t ch; 489 486 while ((ch = str_decode(src, &src_off, STR_NO_LIMIT)) != 0) { 490 487 if (chr_encode(ch, dest, &dest_off, size - 1) != EOK) 491 488 break; 492 489 } 493 490 494 491 dest[dest_off] = '\0'; 495 492 } … … 505 502 * have to be null-terminated. 506 503 * 507 * @param dest Destination buffer.504 * @param dest Destination buffer. 508 505 * @param count Size of the destination buffer (must be > 0). 509 506 * @param src Source string. 510 * @param n Maximum number of bytes to read from @a src.507 * @param n Maximum number of bytes to read from @a src. 511 508 */ 512 509 void str_ncpy(char *dest, size_t size, const char *src, size_t n) 513 510 { 514 wchar_t ch;515 size_t src_off;516 size_t dest_off;517 518 511 /* There must be space for a null terminator in the buffer. */ 519 512 assert(size > 0); 520 513 521 src_off = 0; 522 dest_off = 0; 523 514 size_t src_off = 0; 515 size_t dest_off = 0; 516 517 wchar_t ch; 524 518 while ((ch = str_decode(src, &src_off, n)) != 0) { 525 519 if (chr_encode(ch, dest, &dest_off, size - 1) != EOK) 526 520 break; 527 521 } 528 522 529 523 dest[dest_off] = '\0'; 530 524 } … … 896 890 } 897 891 892 /** Duplicate string. 893 * 894 * Allocate a new string and copy characters from the source 895 * string into it. The duplicate string is allocated via sleeping 896 * malloc(), thus this function can sleep in no memory conditions. 897 * 898 * The allocation cannot fail and the return value is always 899 * a valid pointer. The duplicate string is always a well-formed 900 * null-terminated UTF-8 string, but it can differ from the source 901 * string on the byte level. 902 * 903 * @param src Source string. 904 * 905 * @return Duplicate string. 906 * 907 */ 898 908 char *str_dup(const char *src) 899 909 { 900 size_t size = str_size(src); 901 void *dest = malloc(size + 1); 902 910 size_t size = str_size(src) + 1; 911 char *dest = (char *) malloc(size); 903 912 if (dest == NULL) 904 913 return (char *) NULL; 905 914 906 return (char *) memcpy(dest, src, size + 1); 907 } 908 909 char *str_ndup(const char *src, size_t max_size) 915 str_cpy(dest, size, src); 916 return dest; 917 } 918 919 /** Duplicate string with size limit. 920 * 921 * Allocate a new string and copy up to @max_size bytes from the source 922 * string into it. The duplicate string is allocated via sleeping 923 * malloc(), thus this function can sleep in no memory conditions. 924 * No more than @max_size + 1 bytes is allocated, but if the size 925 * occupied by the source string is smaller than @max_size + 1, 926 * less is allocated. 927 * 928 * The allocation cannot fail and the return value is always 929 * a valid pointer. The duplicate string is always a well-formed 930 * null-terminated UTF-8 string, but it can differ from the source 931 * string on the byte level. 932 * 933 * @param src Source string. 934 * @param n Maximum number of bytes to duplicate. 935 * 936 * @return Duplicate string. 937 * 938 */ 939 char *str_ndup(const char *src, size_t n) 910 940 { 911 941 size_t size = str_size(src); 912 if (size > max_size)913 size = max_size;942 if (size > n) 943 size = n; 914 944 915 945 char *dest = (char *) malloc(size + 1); 916 917 946 if (dest == NULL) 918 947 return (char *) NULL; 919 948 920 memcpy(dest, src, size); 921 dest[size] = 0; 949 str_ncpy(dest, size + 1, src, size); 922 950 return dest; 923 951 } … … 979 1007 } 980 1008 1009 void order_suffix(const uint64_t val, uint64_t *rv, char *suffix) 1010 { 1011 if (val > 10000000000000000000ULL) { 1012 *rv = val / 1000000000000000000ULL; 1013 *suffix = 'Z'; 1014 } else if (val > 1000000000000000000ULL) { 1015 *rv = val / 1000000000000000ULL; 1016 *suffix = 'E'; 1017 } else if (val > 1000000000000000ULL) { 1018 *rv = val / 1000000000000ULL; 1019 *suffix = 'T'; 1020 } else if (val > 1000000000000ULL) { 1021 *rv = val / 1000000000ULL; 1022 *suffix = 'G'; 1023 } else if (val > 1000000000ULL) { 1024 *rv = val / 1000000ULL; 1025 *suffix = 'M'; 1026 } else if (val > 1000000ULL) { 1027 *rv = val / 1000ULL; 1028 *suffix = 'k'; 1029 } else { 1030 *rv = val; 1031 *suffix = ' '; 1032 } 1033 } 1034 981 1035 /** @} 982 1036 */ -
uspace/lib/c/generic/task.c
rcf8cc36 rc47e1a8 39 39 #include <errno.h> 40 40 #include <loader/loader.h> 41 #include <str ing.h>41 #include <str.h> 42 42 #include <ipc/ns.h> 43 43 #include <macros.h> … … 70 70 * loader API. 71 71 * 72 * @param path pathname of the binary to execute 73 * @param argv command-line arguments 72 * @param path Pathname of the binary to execute. 73 * @param argv Command-line arguments. 74 * @param err If not NULL, the error value is stored here. 74 75 * 75 76 * @return ID of the newly created task or zero on error. 76 77 * 77 78 */ 78 task_id_t task_spawn(const char *path, c har *const args[])79 task_id_t task_spawn(const char *path, const char *const args[], int *err) 79 80 { 80 81 /* Connect to a program loader. */ 81 82 loader_t *ldr = loader_connect(); 82 if (ldr == NULL) 83 if (ldr == NULL) { 84 if (err != NULL) 85 *err = EREFUSED; 86 83 87 return 0; 88 } 84 89 85 90 /* Get task ID. */ … … 143 148 /* Success */ 144 149 free(ldr); 150 151 if (err != NULL) 152 *err = EOK; 153 145 154 return task_id; 146 155 … … 149 158 loader_abort(ldr); 150 159 free(ldr); 160 161 if (err != NULL) 162 *err = rc; 151 163 152 164 return 0; -
uspace/lib/c/generic/thread.c
rcf8cc36 rc47e1a8 39 39 #include <kernel/proc/uarg.h> 40 40 #include <fibril.h> 41 #include <str ing.h>41 #include <str.h> 42 42 #include <async.h> 43 43 … … 86 86 * @return Zero on success or a code from @ref errno.h on failure. 87 87 */ 88 int thread_create(void (* function)(void *), void *arg, c har *name,88 int thread_create(void (* function)(void *), void *arg, const char *name, 89 89 thread_id_t *tid) 90 90 { -
uspace/lib/c/generic/tls.c
rcf8cc36 rc47e1a8 40 40 #include <tls.h> 41 41 #include <malloc.h> 42 #include <str ing.h>42 #include <str.h> 43 43 #include <align.h> 44 44 -
uspace/lib/c/generic/vfs/vfs.c
rcf8cc36 rc47e1a8 35 35 #include <vfs/vfs.h> 36 36 #include <vfs/canonify.h> 37 #include <macros.h> 37 38 #include <stdlib.h> 38 39 #include <unistd.h> … … 48 49 #include <futex.h> 49 50 #include <errno.h> 50 #include <str ing.h>51 #include <str.h> 51 52 #include <devmap.h> 52 53 #include <ipc/vfs.h> … … 434 435 } 435 436 436 off _t lseek(int fildes, off_t offset, int whence)437 { 438 ipcarg_t rc;439 440 futex_down(&vfs_phone_futex);441 async_serialize_start();442 vfs_connect();443 444 ipcarg_t newoffs;445 rc = async_req_3_1(vfs_phone, VFS_IN_SEEK, fildes, offset, whence,446 &newoff s);447 448 async_serialize_end(); 449 futex_up(&vfs_phone_futex); 450 437 off64_t lseek(int fildes, off64_t offset, int whence) 438 { 439 futex_down(&vfs_phone_futex); 440 async_serialize_start(); 441 vfs_connect(); 442 443 ipcarg_t newoff_lo; 444 ipcarg_t newoff_hi; 445 ipcarg_t rc = async_req_4_2(vfs_phone, VFS_IN_SEEK, fildes, 446 LOWER32(offset), UPPER32(offset), whence, 447 &newoff_lo, &newoff_hi); 448 449 async_serialize_end(); 450 futex_up(&vfs_phone_futex); 451 451 452 if (rc != EOK) 452 return (off_t) -1; 453 454 return (off_t) newoffs; 455 } 456 457 int ftruncate(int fildes, off_t length) 458 { 459 ipcarg_t rc; 460 461 futex_down(&vfs_phone_futex); 462 async_serialize_start(); 463 vfs_connect(); 464 465 rc = async_req_2_0(vfs_phone, VFS_IN_TRUNCATE, fildes, length); 466 async_serialize_end(); 467 futex_up(&vfs_phone_futex); 453 return (off64_t) -1; 454 455 return (off64_t) MERGE_LOUP32(newoff_lo, newoff_hi); 456 } 457 458 int ftruncate(int fildes, aoff64_t length) 459 { 460 ipcarg_t rc; 461 462 futex_down(&vfs_phone_futex); 463 async_serialize_start(); 464 vfs_connect(); 465 466 rc = async_req_3_0(vfs_phone, VFS_IN_TRUNCATE, fildes, 467 LOWER32(length), UPPER32(length)); 468 async_serialize_end(); 469 futex_up(&vfs_phone_futex); 470 468 471 return (int) rc; 469 472 } … … 479 482 480 483 req = async_send_1(vfs_phone, VFS_IN_FSTAT, fildes, NULL); 481 rc = async_data_read_start(vfs_phone, (void *) stat, sizeof(struct stat));484 rc = async_data_read_start(vfs_phone, (void *) stat, sizeof(struct stat)); 482 485 if (rc != EOK) { 483 486 ipcarg_t rc_orig; … … 553 556 if (!abs) { 554 557 free(dirp); 555 return ENOMEM;558 return NULL; 556 559 } 557 560
Note:
See TracChangeset
for help on using the changeset viewer.
