Changeset 76b5a95c in mainline for uspace/lib
- Timestamp:
- 2011-03-23T20:53:30Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 71af5a4
- Parents:
- 5716e9a (diff), ab10b842 (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
- Files:
-
- 1 added
- 28 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/Makefile
r5716e9a r76b5a95c 91 91 generic/loader.c \ 92 92 generic/getopt.c \ 93 generic/adt/list. o\94 generic/adt/hash_table. o\93 generic/adt/list.c \ 94 generic/adt/hash_table.c \ 95 95 generic/adt/dynamic_fifo.c \ 96 96 generic/adt/measured_strings.c \ -
uspace/lib/c/arch/abs32le/_link.ld.in
r5716e9a r76b5a95c 44 44 } :data 45 45 46 . = ALIGN(0x1000);47 48 _heap = .;49 50 46 /DISCARD/ : { 51 47 *(*); -
uspace/lib/c/arch/amd64/_link.ld.in
r5716e9a r76b5a95c 5 5 text PT_LOAD FLAGS(5); 6 6 data PT_LOAD FLAGS(6); 7 debug PT_NOTE; 7 8 } 8 9 … … 13 14 *(.init); 14 15 } :text 16 15 17 .text : { 16 18 *(.text); 17 19 *(.rodata*); 18 20 } :text 19 21 20 22 . = . + 0x1000; 21 23 22 24 .data : { 23 25 *(.data); 24 26 } :data 27 25 28 .tdata : { 26 29 _tdata_start = .; … … 31 34 _tbss_end = .; 32 35 } :data 36 33 37 _tls_alignment = ALIGNOF(.tdata); 38 34 39 .bss : { 35 40 *(COMMON); 36 41 *(.bss); 37 42 } :data 38 39 . = ALIGN(0x1000); 40 _heap = .; 43 44 #ifdef CONFIG_LINE_DEBUG 45 .comment 0 : { *(.comment); } :debug 46 .debug_abbrev 0 : { *(.debug_abbrev); } :debug 47 .debug_aranges 0 : { *(.debug_aranges); } :debug 48 .debug_info 0 : { *(.debug_info); } :debug 49 .debug_line 0 : { *(.debug_line); } :debug 50 .debug_loc 0 : { *(.debug_loc); } :debug 51 .debug_pubnames 0 : { *(.debug_pubnames); } :debug 52 .debug_pubtypes 0 : { *(.debug_pubtypes); } :debug 53 .debug_ranges 0 : { *(.debug_ranges); } :debug 54 .debug_str 0 : { *(.debug_str); } :debug 55 #endif 41 56 42 57 /DISCARD/ : { 43 58 *(*); 44 59 } 45 46 60 } -
uspace/lib/c/arch/arm32/_link.ld.in
r5716e9a r76b5a95c 9 9 SECTIONS { 10 10 . = 0x1000 + SIZEOF_HEADERS; 11 11 12 12 .init : { 13 13 *(.init); 14 } : text 14 } :text 15 15 16 .text : { 16 17 *(.text); 17 18 *(.rodata*); 18 19 } :text 19 20 20 21 . = . + 0x1000; 21 22 22 23 .data : { 23 24 *(.opd); … … 25 26 *(.sdata); 26 27 } :data 28 27 29 .tdata : { 28 30 _tdata_start = .; … … 33 35 _tbss_end = .; 34 36 } :data 37 35 38 _tls_alignment = ALIGNOF(.tdata); 39 36 40 .bss : { 37 41 *(.sbss); 38 42 *(.scommon); 39 40 43 *(COMMON); 44 *(.bss); 41 45 } :data 42 43 . = ALIGN(0x1000);44 _heap = .;45 46 46 47 /DISCARD/ : { 47 48 *(*); 48 49 } 49 50 50 } -
uspace/lib/c/arch/ia32/_link.ld.in
r5716e9a r76b5a95c 5 5 text PT_LOAD FLAGS(5); 6 6 data PT_LOAD FLAGS(6); 7 debug PT_NOTE; 7 8 } 8 9 … … 42 43 } :data 43 44 44 . = ALIGN(0x1000); 45 46 _heap = .; 45 #ifdef CONFIG_LINE_DEBUG 46 .comment 0 : { *(.comment); } :debug 47 .debug_abbrev 0 : { *(.debug_abbrev); } :debug 48 .debug_aranges 0 : { *(.debug_aranges); } :debug 49 .debug_info 0 : { *(.debug_info); } :debug 50 .debug_line 0 : { *(.debug_line); } :debug 51 .debug_loc 0 : { *(.debug_loc); } :debug 52 .debug_pubnames 0 : { *(.debug_pubnames); } :debug 53 .debug_pubtypes 0 : { *(.debug_pubtypes); } :debug 54 .debug_ranges 0 : { *(.debug_ranges); } :debug 55 .debug_str 0 : { *(.debug_str); } :debug 56 #endif 47 57 48 58 /DISCARD/ : { -
uspace/lib/c/arch/ia64/_link.ld.in
r5716e9a r76b5a95c 9 9 SECTIONS { 10 10 . = 0x4000 + SIZEOF_HEADERS; 11 11 12 12 .init : { 13 13 *(.init); 14 } : text 14 } :text 15 15 16 .text : { 16 17 *(.text); 17 18 *(.rodata*); 18 19 } :text 19 20 20 21 . = . + 0x4000; 21 22 22 23 .got : { 23 24 _gp = .; 24 25 *(.got*); 25 } :data 26 } :data 27 26 28 .data : { 27 29 *(.opd); … … 29 31 *(.sdata); 30 32 } :data 33 31 34 .tdata : { 32 35 _tdata_start = .; … … 37 40 _tbss_end = .; 38 41 } :data 42 39 43 _tls_alignment = ALIGNOF(.tdata); 44 40 45 .bss : { 41 46 *(.sbss); … … 44 49 *(.bss); 45 50 } :data 46 47 . = ALIGN(0x4000); 48 _heap = .; 49 51 50 52 /DISCARD/ : { 51 53 *(*); 52 54 } 53 55 } -
uspace/lib/c/arch/mips32/_link.ld.in
r5716e9a r76b5a95c 13 13 *(.init); 14 14 } :text 15 15 16 .text : { 16 17 *(.text); 17 18 *(.rodata*); 18 19 } :text 19 20 20 21 . = . + 0x4000; 21 22 22 23 .data : { 23 24 *(.data); 24 25 *(.data.rel*); 25 26 } :data 26 27 27 28 .got : { 28 29 _gp = .; 29 30 *(.got); 30 31 } :data 31 32 32 33 .tdata : { 33 34 _tdata_start = .; 34 35 *(.tdata); 35 36 _tdata_end = .; 37 } :data 38 39 .tbss : { 36 40 _tbss_start = .; 37 41 *(.tbss); 38 42 _tbss_end = .; 39 43 } :data 40 _tls_alignment = ALIGNOF(.tdata); 41 44 45 _tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)); 46 42 47 .sbss : { 43 48 *(.scommon); 44 49 *(.sbss); 45 } 50 } 51 46 52 .bss : { 47 53 *(.bss); 48 54 *(COMMON); 49 55 } :data 50 51 . = ALIGN(0x4000); 52 _heap = .; 53 56 54 57 /DISCARD/ : { 55 58 *(*); -
uspace/lib/c/arch/mips32/src/entry.s
r5716e9a r76b5a95c 29 29 .text 30 30 .section .init, "ax" 31 31 32 .global __entry 32 .global __entry_driver 33 33 34 .set noreorder 34 35 .option pic2 … … 57 58 nop 58 59 .end 59 60 # Alignment of output section data to 0x400061 .section .data62 .align 14 -
uspace/lib/c/arch/ppc32/_link.ld.in
r5716e9a r76b5a95c 9 9 SECTIONS { 10 10 . = 0x1000 + SIZEOF_HEADERS; 11 11 12 12 .init : { 13 13 *(.init); 14 14 } :text 15 15 16 .text : { 16 17 *(.text); 17 18 *(.rodata*); 18 19 } :text 19 20 20 21 . = . + 0x1000; 21 22 22 23 .data : { 23 24 *(.data); 24 25 *(.sdata); 25 26 } :data 27 26 28 .tdata : { 27 29 _tdata_start = .; … … 32 34 _tbss_end = .; 33 35 } :data 36 34 37 _tls_alignment = ALIGNOF(.tdata); 38 35 39 .bss : { 36 40 *(.sbss); … … 38 42 *(.bss); 39 43 } :data 40 41 . = ALIGN(0x1000);42 _heap = .;43 44 44 45 /DISCARD/ : { 45 46 *(*); 46 47 } 47 48 48 } -
uspace/lib/c/arch/sparc64/_link.ld.in
r5716e9a r76b5a95c 9 9 SECTIONS { 10 10 . = 0x4000 + SIZEOF_HEADERS; 11 11 12 12 .init : { 13 13 *(.init); 14 14 } :text 15 15 16 .text : { 16 17 *(.text); 17 18 *(.rodata*); 18 19 } :text 19 20 20 21 . = . + 0x4000; 21 22 22 23 .got : { 23 24 _gp = .; 24 25 *(.got*); 25 26 } :data 27 26 28 .data : { 27 29 *(.data); 28 30 *(.sdata); 29 31 } :data 32 30 33 .tdata : { 31 34 _tdata_start = .; … … 36 39 _tbss_end = .; 37 40 } :data 41 38 42 _tls_alignment = ALIGNOF(.tdata); 43 39 44 .bss : { 40 45 *(.sbss); … … 42 47 *(.bss); 43 48 } :data 44 45 . = ALIGN(0x4000);46 _heap = .;47 49 48 50 /DISCARD/ : { 49 51 *(*); 50 52 } 51 52 53 } -
uspace/lib/c/generic/as.c
r5716e9a r76b5a95c 40 40 #include <bitops.h> 41 41 #include <malloc.h> 42 43 /** Last position allocated by as_get_mappable_page */ 44 static uintptr_t last_allocated = 0; 42 #include "private/libc.h" 45 43 46 44 /** Create address space area. … … 103 101 } 104 102 105 /** Return pointer to some unmapped area, where fits new as_area103 /** Return pointer to unmapped address space area 106 104 * 107 105 * @param size Requested size of the allocation. 108 106 * 109 * @return pointer to the beginning107 * @return Pointer to the beginning of unmapped address space area. 110 108 * 111 109 */ 112 110 void *as_get_mappable_page(size_t size) 113 111 { 114 if (size == 0) 115 return NULL; 116 117 size_t sz = 1 << (fnzb(size - 1) + 1); 118 if (last_allocated == 0) 119 last_allocated = get_max_heap_addr(); 120 121 /* 122 * Make sure we allocate from naturally aligned address. 123 */ 124 uintptr_t res = ALIGN_UP(last_allocated, sz); 125 last_allocated = res + ALIGN_UP(size, PAGE_SIZE); 126 127 return ((void *) res); 112 return (void *) __SYSCALL2(SYS_AS_GET_UNMAPPED_AREA, 113 (sysarg_t) __entry, (sysarg_t) size); 128 114 } 129 115 -
uspace/lib/c/generic/async.c
r5716e9a r76b5a95c 430 430 431 431 fid_t fid = fibril_create(notification_fibril, msg); 432 if (fid == 0) { 433 free(msg); 434 futex_up(&async_futex); 435 return false; 436 } 437 432 438 fibril_add_ready(fid); 433 439 … … 681 687 conn->wdata.fid = fibril_create(connection_fibril, conn); 682 688 683 if ( !conn->wdata.fid) {689 if (conn->wdata.fid == 0) { 684 690 free(conn); 691 685 692 if (callid) 686 693 ipc_answer_0(callid, ENOMEM); 694 687 695 return (uintptr_t) NULL; 688 696 } … … 853 861 { 854 862 fid_t fid = fibril_create(async_manager_fibril, NULL); 855 fibril_add_manager(fid); 863 if (fid != 0) 864 fibril_add_manager(fid); 856 865 } 857 866 -
uspace/lib/c/generic/devman.c
r5716e9a r76b5a95c 123 123 } 124 124 125 static int devman_send_match_id(int phone, match_id_t *match_id) \ 126 { 127 ipc_call_t answer; 128 aid_t req = async_send_1(phone, DEVMAN_ADD_MATCH_ID, match_id->score, &answer); 129 int retval = async_data_write_start(phone, match_id->id, str_size(match_id->id)); 125 static int devman_send_match_id(int phone, match_id_t *match_id) 126 { 127 ipc_call_t answer; 128 129 aid_t req = async_send_1(phone, DEVMAN_ADD_MATCH_ID, match_id->score, 130 &answer); 131 int retval = async_data_write_start(phone, match_id->id, 132 str_size(match_id->id)); 133 130 134 async_wait_for(req, NULL); 131 135 return retval; … … 133 137 134 138 135 static int devman_send_match_ids(int phone, match_id_list_t *match_ids) 139 static int devman_send_match_ids(int phone, match_id_list_t *match_ids) 136 140 { 137 141 link_t *link = match_ids->ids.next; 138 142 match_id_t *match_id = NULL; 139 143 int ret = EOK; 140 144 141 145 while (link != &match_ids->ids) { 142 146 match_id = list_get_instance(link, match_id_t, link); 143 if (EOK != (ret = devman_send_match_id(phone, match_id))) 144 { 145 printf("Driver failed to send match id, error number = %d\n", ret); 146 return ret; 147 } 147 ret = devman_send_match_id(phone, match_id); 148 if (ret != EOK) { 149 printf("Driver failed to send match id, error %d\n", 150 ret); 151 return ret; 152 } 153 148 154 link = link->next; 149 155 } 150 return ret; 151 } 152 153 int devman_child_device_register( 154 const char *name, match_id_list_t *match_ids, devman_handle_t parent_handle, devman_handle_t *handle) 155 { 156 157 return ret; 158 } 159 160 /** Add function to a device. 161 * 162 * Request devman to add a new function to the specified device owned by 163 * this driver task. 164 * 165 * @param name Name of the new function 166 * @param ftype Function type, fun_inner or fun_exposed 167 * @param match_ids Match IDs (should be empty for fun_exposed) 168 * @param devh Devman handle of the device 169 * @param funh Place to store handle of the new function 170 * 171 * @return EOK on success or negative error code. 172 */ 173 int devman_add_function(const char *name, fun_type_t ftype, 174 match_id_list_t *match_ids, devman_handle_t devh, devman_handle_t *funh) 175 { 156 176 int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING); 177 int fun_handle; 157 178 158 179 if (phone < 0) … … 161 182 async_serialize_start(); 162 183 163 int match_count = list_count(&match_ids->ids); 164 ipc_call_t answer; 165 aid_t req = async_send_2(phone, DEVMAN_ADD_CHILD_DEVICE, parent_handle, match_count, &answer); 184 int match_count = list_count(&match_ids->ids); 185 ipc_call_t answer; 186 187 aid_t req = async_send_3(phone, DEVMAN_ADD_FUNCTION, (sysarg_t) ftype, 188 devh, match_count, &answer); 166 189 167 190 sysarg_t retval = async_data_write_start(phone, name, str_size(name)); … … 178 201 async_serialize_end(); 179 202 180 if (retval != EOK) { 181 if (handle != NULL) { 182 *handle = -1; 183 } 184 return retval; 185 } 186 187 if (handle != NULL) 188 *handle = (int) IPC_GET_ARG1(answer); 189 190 return retval; 191 } 192 193 int devman_add_device_to_class(devman_handle_t devman_handle, const char *class_name) 203 if (retval == EOK) 204 fun_handle = (int) IPC_GET_ARG1(answer); 205 else 206 fun_handle = -1; 207 208 *funh = fun_handle; 209 210 return retval; 211 } 212 213 int devman_add_device_to_class(devman_handle_t devman_handle, 214 const char *class_name) 194 215 { 195 216 int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING); … … 200 221 async_serialize_start(); 201 222 ipc_call_t answer; 202 aid_t req = async_send_1(phone, DEVMAN_ADD_DEVICE_TO_CLASS, devman_handle, &answer); 203 204 sysarg_t retval = async_data_write_start(phone, class_name, str_size(class_name)); 223 aid_t req = async_send_1(phone, DEVMAN_ADD_DEVICE_TO_CLASS, 224 devman_handle, &answer); 225 226 sysarg_t retval = async_data_write_start(phone, class_name, 227 str_size(class_name)); 205 228 if (retval != EOK) { 206 229 async_wait_for(req, NULL); … … 212 235 async_serialize_end(); 213 236 214 return retval; 237 return retval; 215 238 } 216 239 … … 265 288 } 266 289 267 int devman_device_get_handle(const char *pathname, devman_handle_t *handle, unsigned int flags) 290 int devman_device_get_handle(const char *pathname, devman_handle_t *handle, 291 unsigned int flags) 268 292 { 269 293 int phone = devman_get_phone(DEVMAN_CLIENT, flags); … … 278 302 &answer); 279 303 280 sysarg_t retval = async_data_write_start(phone, pathname, str_size(pathname)); 304 sysarg_t retval = async_data_write_start(phone, pathname, 305 str_size(pathname)); 281 306 if (retval != EOK) { 282 307 async_wait_for(req, NULL); -
uspace/lib/c/generic/fibril.c
r5716e9a r76b5a95c 115 115 fibril->retval = 0; 116 116 fibril->flags = 0; 117 118 fibril->waits_for = NULL; 117 119 118 120 return fibril; … … 276 278 fibril->arg = arg; 277 279 278 fibril->waits_for = NULL;279 280 280 context_save(&fibril->ctx); 281 281 context_set(&fibril->ctx, FADDR(fibril_main), fibril->stack, -
uspace/lib/c/generic/loader.c
r5716e9a r76b5a95c 160 160 int rc = async_data_write_start(ldr->phone_id, (void *) pa, pa_len); 161 161 if (rc != EOK) { 162 free(pa); 162 163 async_wait_for(req, NULL); 163 164 return rc; -
uspace/lib/c/generic/malloc.c
r5716e9a r76b5a95c 47 47 #include "private/malloc.h" 48 48 49 /* Magic used in heap headers. */ 50 #define HEAP_BLOCK_HEAD_MAGIC 0xBEEF0101 51 52 /* Magic used in heap footers. */ 53 #define HEAP_BLOCK_FOOT_MAGIC 0xBEEF0202 54 55 /** Allocation alignment (this also covers the alignment of fields 56 in the heap header and footer) */ 49 /** Magic used in heap headers. */ 50 #define HEAP_BLOCK_HEAD_MAGIC UINT32_C(0xBEEF0101) 51 52 /** Magic used in heap footers. */ 53 #define HEAP_BLOCK_FOOT_MAGIC UINT32_C(0xBEEF0202) 54 55 /** Magic used in heap descriptor. */ 56 #define HEAP_AREA_MAGIC UINT32_C(0xBEEFCAFE) 57 58 /** Allocation alignment. 59 * 60 * This also covers the alignment of fields 61 * in the heap header and footer. 62 * 63 */ 57 64 #define BASE_ALIGN 16 58 65 59 /** 60 * Either 4 * 256M on 32-bit architecures or 16 * 256M on 64-bit architectures 61 */ 62 #define MAX_HEAP_SIZE (sizeof(uintptr_t) << 28) 63 64 /** 65 * 66 */ 67 #define STRUCT_OVERHEAD (sizeof(heap_block_head_t) + sizeof(heap_block_foot_t)) 68 69 /** 70 * Calculate real size of a heap block (with header and footer) 66 /** Overhead of each heap block. */ 67 #define STRUCT_OVERHEAD \ 68 (sizeof(heap_block_head_t) + sizeof(heap_block_foot_t)) 69 70 /** Calculate real size of a heap block. 71 * 72 * Add header and footer size. 73 * 71 74 */ 72 75 #define GROSS_SIZE(size) ((size) + STRUCT_OVERHEAD) 73 76 74 /** 75 * Calculate net size of a heap block (without header and footer) 77 /** Calculate net size of a heap block. 78 * 79 * Subtract header and footer size. 80 * 76 81 */ 77 82 #define NET_SIZE(size) ((size) - STRUCT_OVERHEAD) 83 84 /** Get first block in heap area. 85 * 86 */ 87 #define AREA_FIRST_BLOCK(area) \ 88 (ALIGN_UP(((uintptr_t) (area)) + sizeof(heap_area_t), BASE_ALIGN)) 89 90 /** Get footer in heap block. 91 * 92 */ 93 #define BLOCK_FOOT(head) \ 94 ((heap_block_foot_t *) \ 95 (((uintptr_t) head) + head->size - sizeof(heap_block_foot_t))) 96 97 /** Heap area. 98 * 99 * The memory managed by the heap allocator is divided into 100 * multiple discontinuous heaps. Each heap is represented 101 * by a separate address space area which has this structure 102 * at its very beginning. 103 * 104 */ 105 typedef struct heap_area { 106 /** Start of the heap area (including this structure) 107 * 108 * Aligned on page boundary. 109 * 110 */ 111 void *start; 112 113 /** End of the heap area (aligned on page boundary) */ 114 void *end; 115 116 /** Next heap area */ 117 struct heap_area *next; 118 119 /** A magic value */ 120 uint32_t magic; 121 } heap_area_t; 78 122 79 123 /** Header of a heap block … … 87 131 bool free; 88 132 133 /** Heap area this block belongs to */ 134 heap_area_t *area; 135 89 136 /* A magic value to detect overwrite of heap header */ 90 137 uint32_t magic; … … 102 149 } heap_block_foot_t; 103 150 104 /** Linker heap symbol */ 105 extern char _heap; 151 /** First heap area */ 152 static heap_area_t *first_heap_area = NULL; 153 154 /** Last heap area */ 155 static heap_area_t *last_heap_area = NULL; 156 157 /** Next heap block to examine (next fit algorithm) */ 158 static heap_block_head_t *next = NULL; 106 159 107 160 /** Futex for thread-safe heap manipulation */ 108 161 static futex_t malloc_futex = FUTEX_INITIALIZER; 109 162 110 /** Address of heap start */111 static void *heap_start = 0;112 113 /** Address of heap end */114 static void *heap_end = 0;115 116 /** Maximum heap size */117 static size_t max_heap_size = (size_t) -1;118 119 /** Current number of pages of heap area */120 static size_t heap_pages = 0;121 122 163 /** Initialize a heap block 123 164 * 124 * Fill sin the structures related to a heap block.165 * Fill in the structures related to a heap block. 125 166 * Should be called only inside the critical section. 126 167 * … … 128 169 * @param size Size of the block including the header and the footer. 129 170 * @param free Indication of a free block. 130 * 131 */ 132 static void block_init(void *addr, size_t size, bool free) 171 * @param area Heap area the block belongs to. 172 * 173 */ 174 static void block_init(void *addr, size_t size, bool free, heap_area_t *area) 133 175 { 134 176 /* Calculate the position of the header and the footer */ 135 177 heap_block_head_t *head = (heap_block_head_t *) addr; 136 heap_block_foot_t *foot =137 (heap_block_foot_t *) (addr + size - sizeof(heap_block_foot_t));138 178 139 179 head->size = size; 140 180 head->free = free; 181 head->area = area; 141 182 head->magic = HEAP_BLOCK_HEAD_MAGIC; 183 184 heap_block_foot_t *foot = BLOCK_FOOT(head); 142 185 143 186 foot->size = size; … … 160 203 assert(head->magic == HEAP_BLOCK_HEAD_MAGIC); 161 204 162 heap_block_foot_t *foot = 163 (heap_block_foot_t *) (addr + head->size - sizeof(heap_block_foot_t)); 205 heap_block_foot_t *foot = BLOCK_FOOT(head); 164 206 165 207 assert(foot->magic == HEAP_BLOCK_FOOT_MAGIC); … … 167 209 } 168 210 169 /** Increase the heap area size 170 * 171 * Should be called only inside the critical section. 172 * 173 * @param size Number of bytes to grow the heap by. 174 * 175 */ 176 static bool grow_heap(size_t size) 211 /** Check a heap area structure 212 * 213 * @param addr Address of the heap area. 214 * 215 */ 216 static void area_check(void *addr) 217 { 218 heap_area_t *area = (heap_area_t *) addr; 219 220 assert(area->magic == HEAP_AREA_MAGIC); 221 assert(area->start < area->end); 222 assert(((uintptr_t) area->start % PAGE_SIZE) == 0); 223 assert(((uintptr_t) area->end % PAGE_SIZE) == 0); 224 } 225 226 /** Create new heap area 227 * 228 * @param start Preffered starting address of the new area. 229 * @param size Size of the area. 230 * 231 */ 232 static bool area_create(size_t size) 233 { 234 void *start = as_get_mappable_page(size); 235 if (start == NULL) 236 return false; 237 238 /* Align the heap area on page boundary */ 239 void *astart = (void *) ALIGN_UP((uintptr_t) start, PAGE_SIZE); 240 size_t asize = ALIGN_UP(size, PAGE_SIZE); 241 242 astart = as_area_create(astart, asize, AS_AREA_WRITE | AS_AREA_READ); 243 if (astart == (void *) -1) 244 return false; 245 246 heap_area_t *area = (heap_area_t *) astart; 247 248 area->start = astart; 249 area->end = (void *) 250 ALIGN_DOWN((uintptr_t) astart + asize, BASE_ALIGN); 251 area->next = NULL; 252 area->magic = HEAP_AREA_MAGIC; 253 254 void *block = (void *) AREA_FIRST_BLOCK(area); 255 size_t bsize = (size_t) (area->end - block); 256 257 block_init(block, bsize, true, area); 258 259 if (last_heap_area == NULL) { 260 first_heap_area = area; 261 last_heap_area = area; 262 } else { 263 last_heap_area->next = area; 264 last_heap_area = area; 265 } 266 267 return true; 268 } 269 270 /** Try to enlarge a heap area 271 * 272 * @param area Heap area to grow. 273 * @param size Gross size of item to allocate (bytes). 274 * 275 */ 276 static bool area_grow(heap_area_t *area, size_t size) 177 277 { 178 278 if (size == 0) 279 return true; 280 281 area_check(area); 282 283 size_t asize = ALIGN_UP((size_t) (area->end - area->start) + size, 284 PAGE_SIZE); 285 286 /* New heap area size */ 287 void *end = (void *) 288 ALIGN_DOWN((uintptr_t) area->start + asize, BASE_ALIGN); 289 290 /* Check for overflow */ 291 if (end < area->start) 179 292 return false; 180 181 if ((heap_start + size < heap_start) || (heap_end + size < heap_end)) 293 294 /* Resize the address space area */ 295 int ret = as_area_resize(area->start, asize, 0); 296 if (ret != EOK) 182 297 return false; 183 298 184 size_t heap_size = (size_t) (heap_end - heap_start); 185 186 if ((max_heap_size != (size_t) -1) && (heap_size + size > max_heap_size)) 187 return false; 188 189 size_t pages = (size - 1) / PAGE_SIZE + 1; 190 191 if (as_area_resize((void *) &_heap, (heap_pages + pages) * PAGE_SIZE, 0) 192 == EOK) { 193 void *end = (void *) ALIGN_DOWN(((uintptr_t) &_heap) + 194 (heap_pages + pages) * PAGE_SIZE, BASE_ALIGN); 195 block_init(heap_end, end - heap_end, true); 196 heap_pages += pages; 197 heap_end = end; 299 /* Add new free block */ 300 block_init(area->end, (size_t) (end - area->end), true, area); 301 302 /* Update heap area parameters */ 303 area->end = end; 304 305 return true; 306 } 307 308 /** Try to enlarge any of the heap areas 309 * 310 * @param size Gross size of item to allocate (bytes). 311 * 312 */ 313 static bool heap_grow(size_t size) 314 { 315 if (size == 0) 198 316 return true; 199 } 200 201 return false; 202 } 203 204 /** Decrease the heap area 205 * 206 * Should be called only inside the critical section. 207 * 208 * @param size Number of bytes to shrink the heap by. 209 * 210 */ 211 static void shrink_heap(void) 212 { 213 // TODO 317 318 /* First try to enlarge some existing area */ 319 heap_area_t *area; 320 for (area = first_heap_area; area != NULL; area = area->next) { 321 if (area_grow(area, size)) 322 return true; 323 } 324 325 /* Eventually try to create a new area */ 326 return area_create(AREA_FIRST_BLOCK(size)); 327 } 328 329 /** Try to shrink heap space 330 * 331 * In all cases the next pointer is reset. 332 * 333 */ 334 static void heap_shrink(void) 335 { 336 next = NULL; 214 337 } 215 338 … … 223 346 void __malloc_init(void) 224 347 { 225 if (!as_area_create((void *) &_heap, PAGE_SIZE, 226 AS_AREA_WRITE | AS_AREA_READ)) 348 if (!area_create(PAGE_SIZE)) 227 349 abort(); 228 229 heap_pages = 1;230 heap_start = (void *) ALIGN_UP((uintptr_t) &_heap, BASE_ALIGN);231 heap_end =232 (void *) ALIGN_DOWN(((uintptr_t) &_heap) + PAGE_SIZE, BASE_ALIGN);233 234 /* Make the entire area one large block. */235 block_init(heap_start, heap_end - heap_start, true);236 }237 238 /** Get maximum heap address239 *240 */241 uintptr_t get_max_heap_addr(void)242 {243 futex_down(&malloc_futex);244 245 if (max_heap_size == (size_t) -1)246 max_heap_size =247 max((size_t) (heap_end - heap_start), MAX_HEAP_SIZE);248 249 uintptr_t max_heap_addr = (uintptr_t) heap_start + max_heap_size;250 251 futex_up(&malloc_futex);252 253 return max_heap_addr;254 350 } 255 351 … … 273 369 /* Block big enough -> split. */ 274 370 void *next = ((void *) cur) + size; 275 block_init(next, cur->size - size, true );276 block_init(cur, size, false );371 block_init(next, cur->size - size, true, cur->area); 372 block_init(cur, size, false, cur->area); 277 373 } else { 278 374 /* Block too small -> use as is. */ … … 281 377 } 282 378 283 /** Allocate a memoryblock379 /** Allocate memory from heap area starting from given block 284 380 * 285 381 * Should be called only inside the critical section. 286 * 287 * @param size The size of the block to allocate.288 * @param align Memory address alignment.289 * 290 * @ return the address of the block or NULL when not enough memory.291 * 292 * /293 static void *malloc_internal(const size_t size, const size_t align) 294 { 295 if (align == 0) 296 return NULL; 297 298 size_t falign = lcm(align, BASE_ALIGN); 299 size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign)); 300 301 bool grown = false; 302 void *result;303 304 loop: 305 result = NULL;306 heap_block_head_t *cur = (heap_block_head_t *) heap_start;307 308 while ((result == NULL) && ((void *) cur < heap_end)) {382 * As a side effect this function also sets the current 383 * pointer on successful allocation. 384 * 385 * @param area Heap area where to allocate from. 386 * @param first_block Starting heap block. 387 * @param final_block Heap block where to finish the search 388 * (may be NULL). 389 * @param real_size Gross number of bytes to allocate. 390 * @param falign Physical alignment of the block. 391 * 392 * @return Address of the allocated block or NULL on not enough memory. 393 * 394 */ 395 static void *malloc_area(heap_area_t *area, heap_block_head_t *first_block, 396 heap_block_head_t *final_block, size_t real_size, size_t falign) 397 { 398 area_check((void *) area); 399 assert((void *) first_block >= (void *) AREA_FIRST_BLOCK(area)); 400 assert((void *) first_block < area->end); 401 402 heap_block_head_t *cur; 403 for (cur = first_block; (void *) cur < area->end; 404 cur = (heap_block_head_t *) (((void *) cur) + cur->size)) { 309 405 block_check(cur); 406 407 /* Finish searching on the final block */ 408 if ((final_block != NULL) && (cur == final_block)) 409 break; 310 410 311 411 /* Try to find a block that is free and large enough. */ 312 412 if ((cur->free) && (cur->size >= real_size)) { 313 /* We have found a suitable block. 314 Check for alignment properties. */ 315 void *addr = ((void *) cur) + sizeof(heap_block_head_t); 316 void *aligned = (void *) ALIGN_UP(addr, falign); 413 /* 414 * We have found a suitable block. 415 * Check for alignment properties. 416 */ 417 void *addr = (void *) 418 ((uintptr_t) cur + sizeof(heap_block_head_t)); 419 void *aligned = (void *) 420 ALIGN_UP((uintptr_t) addr, falign); 317 421 318 422 if (addr == aligned) { 319 423 /* Exact block start including alignment. */ 320 424 split_mark(cur, real_size); 321 result = addr; 425 426 next = cur; 427 return addr; 322 428 } else { 323 429 /* Block start has to be aligned */ … … 325 431 326 432 if (cur->size >= real_size + excess) { 327 /* The current block is large enough to fit 328 data in including alignment */ 329 if ((void *) cur > heap_start) { 330 /* There is a block before the current block. 331 This previous block can be enlarged to compensate 332 for the alignment excess */ 333 heap_block_foot_t *prev_foot = 334 ((void *) cur) - sizeof(heap_block_foot_t); 433 /* 434 * The current block is large enough to fit 435 * data in (including alignment). 436 */ 437 if ((void *) cur > (void *) AREA_FIRST_BLOCK(area)) { 438 /* 439 * There is a block before the current block. 440 * This previous block can be enlarged to 441 * compensate for the alignment excess. 442 */ 443 heap_block_foot_t *prev_foot = (heap_block_foot_t *) 444 ((void *) cur - sizeof(heap_block_foot_t)); 335 445 336 heap_block_head_t *prev_head = 337 ( heap_block_head_t *) (((void *) cur)- prev_foot->size);446 heap_block_head_t *prev_head = (heap_block_head_t *) 447 ((void *) cur - prev_foot->size); 338 448 339 449 block_check(prev_head); … … 342 452 heap_block_head_t *next_head = ((void *) cur) + excess; 343 453 344 if ((!prev_head->free) && (excess >= STRUCT_OVERHEAD)) { 345 /* The previous block is not free and there is enough 346 space to fill in a new free block between the previous 347 and current block */ 348 block_init(cur, excess, true); 454 if ((!prev_head->free) && 455 (excess >= STRUCT_OVERHEAD)) { 456 /* 457 * The previous block is not free and there 458 * is enough free space left to fill in 459 * a new free block between the previous 460 * and current block. 461 */ 462 block_init(cur, excess, true, area); 349 463 } else { 350 /* The previous block is free (thus there is no need to 351 induce additional fragmentation to the heap) or the 352 excess is small, thus just enlarge the previous block */ 353 block_init(prev_head, prev_head->size + excess, prev_head->free); 464 /* 465 * The previous block is free (thus there 466 * is no need to induce additional 467 * fragmentation to the heap) or the 468 * excess is small. Therefore just enlarge 469 * the previous block. 470 */ 471 block_init(prev_head, prev_head->size + excess, 472 prev_head->free, area); 354 473 } 355 474 356 block_init(next_head, reduced_size, true );475 block_init(next_head, reduced_size, true, area); 357 476 split_mark(next_head, real_size); 358 result = aligned; 359 cur = next_head; 477 478 next = next_head; 479 return aligned; 360 480 } else { 361 /* The current block is the first block on the heap. 362 We have to make sure that the alignment excess 363 is large enough to fit a new free block just 364 before the current block */ 481 /* 482 * The current block is the first block 483 * in the heap area. We have to make sure 484 * that the alignment excess is large enough 485 * to fit a new free block just before the 486 * current block. 487 */ 365 488 while (excess < STRUCT_OVERHEAD) { 366 489 aligned += falign; … … 371 494 if (cur->size >= real_size + excess) { 372 495 size_t reduced_size = cur->size - excess; 373 cur = (heap_block_head_t *) (heap_start + excess); 496 cur = (heap_block_head_t *) 497 (AREA_FIRST_BLOCK(area) + excess); 374 498 375 block_init(heap_start, excess, true); 376 block_init(cur, reduced_size, true); 499 block_init((void *) AREA_FIRST_BLOCK(area), excess, 500 true, area); 501 block_init(cur, reduced_size, true, area); 377 502 split_mark(cur, real_size); 378 result = aligned; 503 504 next = cur; 505 return aligned; 379 506 } 380 507 } … … 382 509 } 383 510 } 384 385 /* Advance to the next block. */ 386 cur = (heap_block_head_t *) (((void *) cur) + cur->size); 387 } 388 389 if ((result == NULL) && (!grown)) { 390 if (grow_heap(real_size)) { 391 grown = true; 511 } 512 513 return NULL; 514 } 515 516 /** Allocate a memory block 517 * 518 * Should be called only inside the critical section. 519 * 520 * @param size The size of the block to allocate. 521 * @param align Memory address alignment. 522 * 523 * @return Address of the allocated block or NULL on not enough memory. 524 * 525 */ 526 static void *malloc_internal(const size_t size, const size_t align) 527 { 528 assert(first_heap_area != NULL); 529 530 if (align == 0) 531 return NULL; 532 533 size_t falign = lcm(align, BASE_ALIGN); 534 size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign)); 535 536 bool retry = false; 537 heap_block_head_t *split; 538 539 loop: 540 541 /* Try the next fit approach */ 542 split = next; 543 544 if (split != NULL) { 545 void *addr = malloc_area(split->area, split, NULL, real_size, 546 falign); 547 548 if (addr != NULL) 549 return addr; 550 } 551 552 /* Search the entire heap */ 553 heap_area_t *area; 554 for (area = first_heap_area; area != NULL; area = area->next) { 555 heap_block_head_t *first = (heap_block_head_t *) 556 AREA_FIRST_BLOCK(area); 557 558 void *addr = malloc_area(area, first, split, real_size, 559 falign); 560 561 if (addr != NULL) 562 return addr; 563 } 564 565 if (!retry) { 566 /* Try to grow the heap space */ 567 if (heap_grow(real_size)) { 568 retry = true; 392 569 goto loop; 393 570 } 394 571 } 395 572 396 return result;573 return NULL; 397 574 } 398 575 … … 473 650 (heap_block_head_t *) (addr - sizeof(heap_block_head_t)); 474 651 475 assert((void *) head >= heap_start);476 assert((void *) head < heap_end);477 478 652 block_check(head); 479 653 assert(!head->free); 654 655 heap_area_t *area = head->area; 656 657 area_check(area); 658 assert((void *) head >= (void *) AREA_FIRST_BLOCK(area)); 659 assert((void *) head < area->end); 480 660 481 661 void *ptr = NULL; … … 487 667 /* Shrink */ 488 668 if (orig_size - real_size >= STRUCT_OVERHEAD) { 489 /* Split the original block to a full block 490 and a trailing free block */ 491 block_init((void *) head, real_size, false); 669 /* 670 * Split the original block to a full block 671 * and a trailing free block. 672 */ 673 block_init((void *) head, real_size, false, area); 492 674 block_init((void *) head + real_size, 493 orig_size - real_size, true );494 shrink_heap();675 orig_size - real_size, true, area); 676 heap_shrink(); 495 677 } 496 678 497 679 ptr = ((void *) head) + sizeof(heap_block_head_t); 498 680 } else { 499 /* Look at the next block. If it is free and the size is 500 sufficient then merge the two. Otherwise just allocate 501 a new block, copy the original data into it and 502 free the original block. */ 681 /* 682 * Look at the next block. If it is free and the size is 683 * sufficient then merge the two. Otherwise just allocate 684 * a new block, copy the original data into it and 685 * free the original block. 686 */ 503 687 heap_block_head_t *next_head = 504 688 (heap_block_head_t *) (((void *) head) + head->size); 505 689 506 if (((void *) next_head < heap_end) &&690 if (((void *) next_head < area->end) && 507 691 (head->size + next_head->size >= real_size) && 508 692 (next_head->free)) { 509 693 block_check(next_head); 510 block_init(head, head->size + next_head->size, false );694 block_init(head, head->size + next_head->size, false, area); 511 695 split_mark(head, real_size); 512 696 513 697 ptr = ((void *) head) + sizeof(heap_block_head_t); 698 next = NULL; 514 699 } else 515 700 reloc = true; … … 542 727 = (heap_block_head_t *) (addr - sizeof(heap_block_head_t)); 543 728 544 assert((void *) head >= heap_start);545 assert((void *) head < heap_end);546 547 729 block_check(head); 548 730 assert(!head->free); 731 732 heap_area_t *area = head->area; 733 734 area_check(area); 735 assert((void *) head >= (void *) AREA_FIRST_BLOCK(area)); 736 assert((void *) head < area->end); 549 737 550 738 /* Mark the block itself as free. */ … … 555 743 = (heap_block_head_t *) (((void *) head) + head->size); 556 744 557 if ((void *) next_head < heap_end) {745 if ((void *) next_head < area->end) { 558 746 block_check(next_head); 559 747 if (next_head->free) 560 block_init(head, head->size + next_head->size, true );748 block_init(head, head->size + next_head->size, true, area); 561 749 } 562 750 563 751 /* Look at the previous block. If it is free, merge the two. */ 564 if ((void *) head > heap_start) {752 if ((void *) head > (void *) AREA_FIRST_BLOCK(area)) { 565 753 heap_block_foot_t *prev_foot = 566 754 (heap_block_foot_t *) (((void *) head) - sizeof(heap_block_foot_t)); … … 572 760 573 761 if (prev_head->free) 574 block_init(prev_head, prev_head->size + head->size, true); 575 } 576 577 shrink_heap(); 762 block_init(prev_head, prev_head->size + head->size, true, 763 area); 764 } 765 766 heap_shrink(); 578 767 579 768 futex_up(&malloc_futex); -
uspace/lib/c/generic/private/libc.h
r5716e9a r76b5a95c 36 36 #define LIBC_PRIVATE_LIBC_H_ 37 37 38 extern void __entry(void); 39 extern void __main(void *) __attribute__((noreturn)); 38 40 extern int main(int, char *[]); 39 extern void __main(void *) __attribute__((noreturn));40 41 41 42 #endif -
uspace/lib/c/include/as.h
r5716e9a r76b5a95c 41 41 #include <libarch/config.h> 42 42 43 static inline size_t SIZE2PAGES(size_t size) 44 { 45 if (size == 0) 46 return 0; 47 48 return (size_t) ((size - 1) >> PAGE_WIDTH) + 1; 49 } 50 51 static inline size_t PAGES2SIZE(size_t pages) 52 { 53 return (size_t) (pages << PAGE_WIDTH); 54 } 55 43 56 extern void *as_area_create(void *address, size_t size, int flags); 44 57 extern int as_area_resize(void *address, size_t size, int flags); -
uspace/lib/c/include/devman.h
r5716e9a r76b5a95c 45 45 46 46 extern int devman_driver_register(const char *, async_client_conn_t); 47 extern int devman_ child_device_register(const char *, match_id_list_t *,47 extern int devman_add_function(const char *, fun_type_t, match_id_list_t *, 48 48 devman_handle_t, devman_handle_t *); 49 49 -
uspace/lib/c/include/ipc/devman.h
r5716e9a r76b5a95c 42 42 43 43 typedef sysarg_t devman_handle_t; 44 45 typedef enum { 46 /** Invalid value for debugging purposes */ 47 fun_invalid = 0, 48 /** Function to which child devices attach */ 49 fun_inner, 50 /** Fuction exported to external clients (leaf function) */ 51 fun_exposed 52 } fun_type_t; 44 53 45 54 /** Ids of device models used for device-to-driver matching. … … 127 136 typedef enum { 128 137 DEVMAN_DRIVER_REGISTER = IPC_FIRST_USER_METHOD, 129 DEVMAN_ADD_ CHILD_DEVICE,138 DEVMAN_ADD_FUNCTION, 130 139 DEVMAN_ADD_MATCH_ID, 131 140 DEVMAN_ADD_DEVICE_TO_CLASS -
uspace/lib/c/include/malloc.h
r5716e9a r76b5a95c 38 38 #include <sys/types.h> 39 39 40 extern uintptr_t get_max_heap_addr(void);41 42 40 extern void *malloc(const size_t size) 43 41 __attribute__((malloc)); -
uspace/lib/c/include/unistd.h
r5716e9a r76b5a95c 44 44 #endif 45 45 46 #define getpagesize() (PAGE_SIZE)47 48 46 #ifndef SEEK_SET 49 47 #define SEEK_SET 0 … … 57 55 #define SEEK_END 2 58 56 #endif 57 58 #define getpagesize() (PAGE_SIZE) 59 59 60 60 extern int dup2(int oldfd, int newfd); -
uspace/lib/drv/generic/driver.c
r5716e9a r76b5a95c 1 1 /* 2 2 * Copyright (c) 2010 Lenka Trochtova 3 * Copyright (c) 2011 Jiri Svoboda 3 4 * All rights reserved. 4 5 * … … 49 50 #include <errno.h> 50 51 #include <inttypes.h> 52 #include <devman.h> 51 53 52 54 #include <ipc/driver.h> 53 55 54 56 #include "dev_iface.h" 55 #include "driver.h" 57 #include "ddf/driver.h" 58 #include "ddf/interrupt.h" 56 59 57 60 /** Driver structure */ … … 59 62 60 63 /** Devices */ 61 LIST_INITIALIZE( devices);62 FIBRIL_MUTEX_INITIALIZE( devices_mutex);64 LIST_INITIALIZE(functions); 65 FIBRIL_MUTEX_INITIALIZE(functions_mutex); 63 66 64 67 /** Interrupts */ … … 76 79 }; 77 80 81 static ddf_dev_t *create_device(void); 82 static void delete_device(ddf_dev_t *); 83 static remote_handler_t *function_get_default_handler(ddf_fun_t *); 84 static void *function_get_ops(ddf_fun_t *, dev_inferface_idx_t); 78 85 79 86 static void driver_irq_handler(ipc_callid_t iid, ipc_call_t *icall) … … 150 157 151 158 interrupt_context_t * 152 find_interrupt_context(interrupt_context_list_t *list, d evice_t *dev, int irq)159 find_interrupt_context(interrupt_context_list_t *list, ddf_dev_t *dev, int irq) 153 160 { 154 161 fibril_mutex_lock(&list->mutex); … … 172 179 173 180 int 174 register_interrupt_handler(d evice_t *dev, int irq, interrupt_handler_t *handler,181 register_interrupt_handler(ddf_dev_t *dev, int irq, interrupt_handler_t *handler, 175 182 irq_code_t *pseudocode) 176 183 { … … 195 202 } 196 203 197 int unregister_interrupt_handler(d evice_t *dev, int irq)204 int unregister_interrupt_handler(ddf_dev_t *dev, int irq) 198 205 { 199 206 interrupt_context_t *ctx = find_interrupt_context(&interrupt_contexts, … … 209 216 } 210 217 211 static void add_to_ devices_list(device_t *dev)212 { 213 fibril_mutex_lock(& devices_mutex);214 list_append(& dev->link, &devices);215 fibril_mutex_unlock(& devices_mutex);216 } 217 218 static void remove_from_ devices_list(device_t *dev)219 { 220 fibril_mutex_lock(& devices_mutex);221 list_remove(& dev->link);222 fibril_mutex_unlock(& devices_mutex);223 } 224 225 static d evice_t *driver_get_device(link_t *devices, devman_handle_t handle)226 { 227 d evice_t *dev= NULL;228 229 fibril_mutex_lock(& devices_mutex);230 link_t *link = devices->next;231 232 while (link != devices) {233 dev = list_get_instance(link, device_t, link);234 if ( dev->handle == handle) {235 fibril_mutex_unlock(& devices_mutex);236 return dev;218 static void add_to_functions_list(ddf_fun_t *fun) 219 { 220 fibril_mutex_lock(&functions_mutex); 221 list_append(&fun->link, &functions); 222 fibril_mutex_unlock(&functions_mutex); 223 } 224 225 static void remove_from_functions_list(ddf_fun_t *fun) 226 { 227 fibril_mutex_lock(&functions_mutex); 228 list_remove(&fun->link); 229 fibril_mutex_unlock(&functions_mutex); 230 } 231 232 static ddf_fun_t *driver_get_function(link_t *functions, devman_handle_t handle) 233 { 234 ddf_fun_t *fun = NULL; 235 236 fibril_mutex_lock(&functions_mutex); 237 link_t *link = functions->next; 238 239 while (link != functions) { 240 fun = list_get_instance(link, ddf_fun_t, link); 241 if (fun->handle == handle) { 242 fibril_mutex_unlock(&functions_mutex); 243 return fun; 237 244 } 245 238 246 link = link->next; 239 247 } 240 248 241 fibril_mutex_unlock(& devices_mutex);249 fibril_mutex_unlock(&functions_mutex); 242 250 243 251 return NULL; … … 250 258 251 259 devman_handle_t dev_handle = IPC_GET_ARG1(*icall); 252 devman_handle_t parent_ dev_handle = IPC_GET_ARG2(*icall);253 254 d evice_t *dev = create_device();260 devman_handle_t parent_fun_handle = IPC_GET_ARG2(*icall); 261 262 ddf_dev_t *dev = create_device(); 255 263 dev->handle = dev_handle; 256 264 257 265 async_data_write_accept((void **) &dev_name, true, 0, 0, 0, 0); 258 266 dev->name = dev_name; 259 260 add_to_devices_list(dev); 261 dev->parent = driver_get_device(&devices, parent_dev_handle); 267 268 /* 269 * Currently not used, parent fun handle is stored in context 270 * of the connection to the parent device driver. 271 */ 272 (void) parent_fun_handle; 262 273 263 274 res = driver->driver_ops->add_device(dev); … … 268 279 printf("%s: failed to add a new device with handle = %" PRIun ".\n", 269 280 driver->name, dev_handle); 270 remove_from_devices_list(dev);271 281 delete_device(dev); 272 282 } … … 311 321 */ 312 322 devman_handle_t handle = IPC_GET_ARG2(*icall); 313 d evice_t *dev = driver_get_device(&devices, handle);314 315 if ( dev== NULL) {316 printf("%s: driver_connection_gen error - no devicewith handle"323 ddf_fun_t *fun = driver_get_function(&functions, handle); 324 325 if (fun == NULL) { 326 printf("%s: driver_connection_gen error - no function with handle" 317 327 " %" PRIun " was found.\n", driver->name, handle); 318 328 async_answer_0(iid, ENOENT); … … 327 337 328 338 int ret = EOK; 329 /* open the device*/330 if ( dev->ops != NULL && dev->ops->open != NULL)331 ret = (* dev->ops->open)(dev);339 /* Open device function */ 340 if (fun->ops != NULL && fun->ops->open != NULL) 341 ret = (*fun->ops->open)(fun); 332 342 333 343 async_answer_0(iid, ret); … … 344 354 switch (method) { 345 355 case IPC_M_PHONE_HUNGUP: 346 /* close the device*/347 if ( dev->ops != NULL && dev->ops->close != NULL)348 (* dev->ops->close)(dev);356 /* Close device function */ 357 if (fun->ops != NULL && fun->ops->close != NULL) 358 (*fun->ops->close)(fun); 349 359 async_answer_0(callid, EOK); 350 360 return; … … 356 366 if (!is_valid_iface_idx(iface_idx)) { 357 367 remote_handler_t *default_handler = 358 device_get_default_handler(dev);368 function_get_default_handler(fun); 359 369 if (default_handler != NULL) { 360 (*default_handler)( dev, callid, &call);370 (*default_handler)(fun, callid, &call); 361 371 break; 362 372 } 373 363 374 /* 364 * This is not device's interface and the375 * Function has no such interface and 365 376 * default handler is not provided. 366 377 */ … … 372 383 } 373 384 374 /* calling one of the device's interfaces */385 /* calling one of the function's interfaces */ 375 386 376 387 /* Get the interface ops structure. */ 377 void *ops = device_get_ops(dev, iface_idx);388 void *ops = function_get_ops(fun, iface_idx); 378 389 if (ops == NULL) { 379 390 printf("%s: driver_connection_gen error - ", 380 391 driver->name); 381 printf(" devicewith handle %" PRIun " has no interface "392 printf("Function with handle %" PRIun " has no interface " 382 393 "with id %d.\n", handle, iface_idx); 383 394 async_answer_0(callid, ENOTSUP); … … 408 419 * receive parameters from the remote client and it will 409 420 * pass it to the corresponding local interface method 410 * associated with the deviceby its driver.421 * associated with the function by its driver. 411 422 */ 412 (*iface_method_ptr)( dev, ops, callid, &call);423 (*iface_method_ptr)(fun, ops, callid, &call); 413 424 break; 414 425 } … … 425 436 driver_connection_gen(iid, icall, false); 426 437 } 427 428 438 429 439 /** Function for handling connections to device driver. */ … … 454 464 * @return The device structure. 455 465 */ 456 device_t *create_device(void)457 { 458 d evice_t *dev = malloc(sizeof(device_t));459 460 if (dev != NULL) {461 memset(dev, 0, sizeof(device_t));462 init_match_ids(&dev->match_ids);463 } 464 466 static ddf_dev_t *create_device(void) 467 { 468 ddf_dev_t *dev; 469 470 dev = malloc(sizeof(ddf_dev_t)); 471 if (dev == NULL) 472 return NULL; 473 474 memset(dev, 0, sizeof(ddf_dev_t)); 465 475 return dev; 466 476 } 467 477 478 /** Create new function structure. 479 * 480 * @return The device structure. 481 */ 482 static ddf_fun_t *create_function(void) 483 { 484 ddf_fun_t *fun; 485 486 fun = calloc(1, sizeof(ddf_fun_t)); 487 if (fun == NULL) 488 return NULL; 489 490 init_match_ids(&fun->match_ids); 491 link_initialize(&fun->link); 492 493 return fun; 494 } 495 468 496 /** Delete device structure. 469 497 * 470 498 * @param dev The device structure. 471 499 */ 472 void delete_device(device_t *dev) 473 { 474 clean_match_ids(&dev->match_ids); 475 if (dev->name != NULL) 476 free(dev->name); 500 static void delete_device(ddf_dev_t *dev) 501 { 477 502 free(dev); 478 503 } 479 504 480 void *device_get_ops(device_t *dev, dev_inferface_idx_t idx) 505 /** Delete device structure. 506 * 507 * @param dev The device structure. 508 */ 509 static void delete_function(ddf_fun_t *fun) 510 { 511 clean_match_ids(&fun->match_ids); 512 if (fun->name != NULL) 513 free(fun->name); 514 free(fun); 515 } 516 517 /** Create a DDF function node. 518 * 519 * Create a DDF function (in memory). Both child devices and external clients 520 * communicate with a device via its functions. 521 * 522 * The created function node is fully formed, but only exists in the memory 523 * of the client task. In order to be visible to the system, the function 524 * must be bound using ddf_fun_bind(). 525 * 526 * This function should only fail if there is not enough free memory. 527 * Specifically, this function succeeds even if @a dev already has 528 * a (bound) function with the same name. 529 * 530 * Type: A function of type fun_inner indicates that DDF should attempt 531 * to attach child devices to the function. fun_exposed means that 532 * the function should be exported to external clients (applications). 533 * 534 * @param dev Device to which we are adding function 535 * @param ftype Type of function (fun_inner or fun_exposed) 536 * @param name Name of function 537 * 538 * @return New function or @c NULL if memory is not available 539 */ 540 ddf_fun_t *ddf_fun_create(ddf_dev_t *dev, fun_type_t ftype, const char *name) 541 { 542 ddf_fun_t *fun; 543 544 fun = create_function(); 545 if (fun == NULL) 546 return NULL; 547 548 fun->bound = false; 549 fun->dev = dev; 550 fun->ftype = ftype; 551 552 fun->name = str_dup(name); 553 if (fun->name == NULL) { 554 delete_function(fun); 555 return NULL; 556 } 557 558 return fun; 559 } 560 561 /** Destroy DDF function node. 562 * 563 * Destroy a function previously created with ddf_fun_create(). The function 564 * must not be bound. 565 * 566 * @param fun Function to destroy 567 */ 568 void ddf_fun_destroy(ddf_fun_t *fun) 569 { 570 assert(fun->bound == false); 571 delete_function(fun); 572 } 573 574 static void *function_get_ops(ddf_fun_t *fun, dev_inferface_idx_t idx) 481 575 { 482 576 assert(is_valid_iface_idx(idx)); 483 if ( dev->ops == NULL)577 if (fun->ops == NULL) 484 578 return NULL; 485 return dev->ops->interfaces[idx]; 486 } 487 488 int child_device_register(device_t *child, device_t *parent) 489 { 490 assert(child->name != NULL); 579 return fun->ops->interfaces[idx]; 580 } 581 582 /** Bind a function node. 583 * 584 * Bind the specified function to the system. This effectively makes 585 * the function visible to the system (uploads it to the server). 586 * 587 * This function can fail for several reasons. Specifically, 588 * it will fail if the device already has a bound function of 589 * the same name. 590 * 591 * @param fun Function to bind 592 * @return EOK on success or negative error code 593 */ 594 int ddf_fun_bind(ddf_fun_t *fun) 595 { 596 assert(fun->name != NULL); 491 597 492 598 int res; 493 599 494 add_to_ devices_list(child);495 res = devman_ child_device_register(child->name, &child->match_ids,496 parent->handle, &child->handle);600 add_to_functions_list(fun); 601 res = devman_add_function(fun->name, fun->ftype, &fun->match_ids, 602 fun->dev->handle, &fun->handle); 497 603 if (res != EOK) { 498 remove_from_ devices_list(child);604 remove_from_functions_list(fun); 499 605 return res; 500 606 } 501 607 608 fun->bound = true; 502 609 return res; 503 610 } 504 611 505 /** Wrapper for child_device_register for devices with single match id. 506 * 507 * @param parent Parent device. 508 * @param child_name Child device name. 509 * @param child_match_id Child device match id. 510 * @param child_match_score Child device match score. 511 * @return Error code. 512 */ 513 int child_device_register_wrapper(device_t *parent, const char *child_name, 514 const char *child_match_id, int child_match_score) 515 { 516 device_t *child = NULL; 517 match_id_t *match_id = NULL; 518 int rc; 519 520 child = create_device(); 521 if (child == NULL) { 522 rc = ENOMEM; 523 goto failure; 524 } 525 526 child->name = child_name; 612 /** Add single match ID to inner function. 613 * 614 * Construct and add a single match ID to the specified function. 615 * Cannot be called when the function node is bound. 616 * 617 * @param fun Function 618 * @param match_id_str Match string 619 * @param match_score Match score 620 * @return EOK on success, ENOMEM if out of memory. 621 */ 622 int ddf_fun_add_match_id(ddf_fun_t *fun, const char *match_id_str, 623 int match_score) 624 { 625 match_id_t *match_id; 626 627 assert(fun->bound == false); 628 assert(fun->ftype == fun_inner); 527 629 528 630 match_id = create_match_id(); 529 if (match_id == NULL) { 530 rc = ENOMEM; 531 goto failure; 532 } 533 534 match_id->id = child_match_id; 535 match_id->score = child_match_score; 536 add_match_id(&child->match_ids, match_id); 537 538 rc = child_device_register(child, parent); 539 if (rc != EOK) 540 goto failure; 541 631 if (match_id == NULL) 632 return ENOMEM; 633 634 match_id->id = match_id_str; 635 match_id->score = 90; 636 637 add_match_id(&fun->match_ids, match_id); 542 638 return EOK; 543 544 failure:545 if (match_id != NULL) {546 match_id->id = NULL;547 delete_match_id(match_id);548 }549 550 if (child != NULL) {551 child->name = NULL;552 delete_device(child);553 }554 555 return rc;556 639 } 557 640 558 641 /** Get default handler for client requests */ 559 remote_handler_t *device_get_default_handler(device_t *dev)560 { 561 if ( dev->ops == NULL)642 static remote_handler_t *function_get_default_handler(ddf_fun_t *fun) 643 { 644 if (fun->ops == NULL) 562 645 return NULL; 563 return dev->ops->default_handler; 564 } 565 566 int add_device_to_class(device_t *dev, const char *class_name) 567 { 568 return devman_add_device_to_class(dev->handle, class_name); 569 } 570 571 int driver_main(driver_t *drv) 646 return fun->ops->default_handler; 647 } 648 649 /** Add exposed function to class. 650 * 651 * Must only be called when the function is bound. 652 */ 653 int ddf_fun_add_to_class(ddf_fun_t *fun, const char *class_name) 654 { 655 assert(fun->bound == true); 656 assert(fun->ftype == fun_exposed); 657 658 return devman_add_device_to_class(fun->handle, class_name); 659 } 660 661 int ddf_driver_main(driver_t *drv) 572 662 { 573 663 /* -
uspace/lib/drv/generic/remote_char_dev.c
r5716e9a r76b5a95c 37 37 38 38 #include "ops/char_dev.h" 39 #include "d river.h"39 #include "ddf/driver.h" 40 40 41 41 #define MAX_CHAR_RW_COUNT 256 42 42 43 static void remote_char_read(d evice_t *, void *, ipc_callid_t, ipc_call_t *);44 static void remote_char_write(d evice_t *, void *, ipc_callid_t, ipc_call_t *);43 static void remote_char_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 44 static void remote_char_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *); 45 45 46 46 /** Remote character interface operations. */ … … 67 67 * local interface to the remote client. 68 68 * 69 * @param dev The devicefrom which the data are read.69 * @param fun The function from which the data are read. 70 70 * @param ops The local ops structure. 71 71 */ 72 72 static void 73 remote_char_read(d evice_t *dev, void *ops, ipc_callid_t callid,73 remote_char_read(ddf_fun_t *fun, void *ops, ipc_callid_t callid, 74 74 ipc_call_t *call) 75 75 { … … 94 94 95 95 char buf[MAX_CHAR_RW_COUNT]; 96 int ret = (*char_dev_ops->read)( dev, buf, len);96 int ret = (*char_dev_ops->read)(fun, buf, len); 97 97 98 98 if (ret < 0) { … … 114 114 * local interface to the remote client. 115 115 * 116 * @param dev The deviceto which the data are written.116 * @param fun The function to which the data are written. 117 117 * @param ops The local ops structure. 118 118 */ 119 119 static void 120 remote_char_write(d evice_t *dev, void *ops, ipc_callid_t callid,120 remote_char_write(ddf_fun_t *fun, void *ops, ipc_callid_t callid, 121 121 ipc_call_t *call) 122 122 { … … 144 144 async_data_write_finalize(cid, buf, len); 145 145 146 int ret = (*char_dev_ops->write)( dev, buf, len);146 int ret = (*char_dev_ops->write)(fun, buf, len); 147 147 if (ret < 0) { 148 148 /* Some error occured. */ -
uspace/lib/drv/generic/remote_hw_res.c
r5716e9a r76b5a95c 37 37 38 38 #include "ops/hw_res.h" 39 #include "d river.h"39 #include "ddf/driver.h" 40 40 41 static void remote_hw_res_get_resource_list(d evice_t *, void *, ipc_callid_t,41 static void remote_hw_res_get_resource_list(ddf_fun_t *, void *, ipc_callid_t, 42 42 ipc_call_t *); 43 static void remote_hw_res_enable_interrupt(d evice_t *, void *, ipc_callid_t,43 static void remote_hw_res_enable_interrupt(ddf_fun_t *, void *, ipc_callid_t, 44 44 ipc_call_t *); 45 45 … … 55 55 }; 56 56 57 static void remote_hw_res_enable_interrupt(d evice_t *dev, void *ops,57 static void remote_hw_res_enable_interrupt(ddf_fun_t *fun, void *ops, 58 58 ipc_callid_t callid, ipc_call_t *call) 59 59 { … … 62 62 if (hw_res_ops->enable_interrupt == NULL) 63 63 async_answer_0(callid, ENOTSUP); 64 else if (hw_res_ops->enable_interrupt( dev))64 else if (hw_res_ops->enable_interrupt(fun)) 65 65 async_answer_0(callid, EOK); 66 66 else … … 68 68 } 69 69 70 static void remote_hw_res_get_resource_list(d evice_t *dev, void *ops,70 static void remote_hw_res_get_resource_list(ddf_fun_t *fun, void *ops, 71 71 ipc_callid_t callid, ipc_call_t *call) 72 72 { … … 78 78 } 79 79 80 hw_resource_list_t *hw_resources = hw_res_ops->get_resource_list( dev);80 hw_resource_list_t *hw_resources = hw_res_ops->get_resource_list(fun); 81 81 if (hw_resources == NULL){ 82 82 async_answer_0(callid, ENOENT); -
uspace/lib/drv/include/ddf/driver.h
r5716e9a r76b5a95c 1 1 /* 2 2 * Copyright (c) 2010 Lenka Trochtova 3 * Copyright (c) 2011 Jiri Svoboda 3 4 * All rights reserved. 4 5 * … … 33 34 */ 34 35 35 #ifndef LIBDRV_DRIVER_H_36 #define LIBDRV_DRIVER_H_36 #ifndef DDF_DRIVER_H_ 37 #define DDF_DRIVER_H_ 37 38 38 #include <kernel/ddi/irq.h>39 #include <adt/list.h>40 #include <devman.h>41 39 #include <ipc/devman.h> 42 40 #include <ipc/dev_iface.h> 43 #include <assert.h>44 #include <ddi.h>45 #include <libarch/ddi.h>46 #include <fibril_synch.h>47 #include <malloc.h>48 41 49 #include " dev_iface.h"42 #include "../dev_iface.h" 50 43 51 struct device;52 typedef struct d evice device_t;44 typedef struct ddf_dev ddf_dev_t; 45 typedef struct ddf_fun ddf_fun_t; 53 46 54 47 /* 55 * Device class48 * Device 56 49 */ 57 50 58 51 /** Devices operations */ 59 typedef struct d evice_ops {52 typedef struct ddf_dev_ops { 60 53 /** 61 54 * Optional callback function called when a client is connecting to the 62 55 * device. 63 56 */ 64 int (*open)(d evice_t *);57 int (*open)(ddf_fun_t *); 65 58 66 59 /** … … 68 61 * the device. 69 62 */ 70 void (*close)(d evice_t *);63 void (*close)(ddf_fun_t *); 71 64 72 65 /** The table of standard interfaces implemented by the device. */ … … 79 72 */ 80 73 remote_handler_t *default_handler; 81 } device_ops_t; 82 83 84 /* 85 * Device 86 */ 74 } ddf_dev_ops_t; 87 75 88 76 /** Device structure */ 89 struct d evice{77 struct ddf_dev { 90 78 /** 91 79 * Globally unique device identifier (assigned to the device by the … … 100 88 int parent_phone; 101 89 102 /** Parent device if handled by this driver, NULL otherwise */103 device_t *parent;104 90 /** Device name */ 105 91 const char *name; 106 /** List of device ids for device-to-driver matching */ 107 match_id_list_t match_ids; 92 108 93 /** Driver-specific data associated with this device */ 109 94 void *driver_data; 110 /** The implementation of operations provided by this device */111 device_ops_t *ops;112 95 113 96 /** Link in the list of devices handled by the driver */ 97 link_t link; 98 }; 99 100 /** Function structure */ 101 struct ddf_fun { 102 /** True if bound to the device manager */ 103 bool bound; 104 /** Function indentifier (asigned by device manager) */ 105 devman_handle_t handle; 106 107 /** Device which this function belogs to */ 108 ddf_dev_t *dev; 109 110 /** Function type */ 111 fun_type_t ftype; 112 /** Function name */ 113 const char *name; 114 /** List of device ids for driver matching */ 115 match_id_list_t match_ids; 116 /** Driver-specific data associated with this function */ 117 void *driver_data; 118 /** Implementation of operations provided by this function */ 119 ddf_dev_ops_t *ops; 120 121 /** Link in the list of functions handled by the driver */ 114 122 link_t link; 115 123 }; … … 122 130 typedef struct driver_ops { 123 131 /** Callback method for passing a new device to the device driver */ 124 int (*add_device)(d evice_t *dev);132 int (*add_device)(ddf_dev_t *dev); 125 133 /* TODO: add other generic driver operations */ 126 134 } driver_ops_t; … … 134 142 } driver_t; 135 143 136 intdriver_main(driver_t *);144 extern int ddf_driver_main(driver_t *); 137 145 138 /** Create new device structure. 139 * 140 * @return The device structure. 141 */ 142 extern device_t *create_device(void); 143 extern void delete_device(device_t *); 144 extern void *device_get_ops(device_t *, dev_inferface_idx_t); 146 extern ddf_fun_t *ddf_fun_create(ddf_dev_t *, fun_type_t, const char *); 147 extern void ddf_fun_destroy(ddf_fun_t *); 148 extern int ddf_fun_bind(ddf_fun_t *); 149 extern int ddf_fun_add_match_id(ddf_fun_t *, const char *, int); 145 150 146 extern int child_device_register(device_t *, device_t *); 147 extern int child_device_register_wrapper(device_t *, const char *, const char *, 148 int); 149 150 /* 151 * Interrupts 152 */ 153 154 typedef void interrupt_handler_t(device_t *, ipc_callid_t, ipc_call_t *); 155 156 typedef struct interrupt_context { 157 int id; 158 device_t *dev; 159 int irq; 160 interrupt_handler_t *handler; 161 link_t link; 162 } interrupt_context_t; 163 164 typedef struct interrupt_context_list { 165 int curr_id; 166 link_t contexts; 167 fibril_mutex_t mutex; 168 } interrupt_context_list_t; 169 170 extern interrupt_context_t *create_interrupt_context(void); 171 extern void delete_interrupt_context(interrupt_context_t *); 172 extern void init_interrupt_context_list(interrupt_context_list_t *); 173 extern void add_interrupt_context(interrupt_context_list_t *, 174 interrupt_context_t *); 175 extern void remove_interrupt_context(interrupt_context_list_t *, 176 interrupt_context_t *); 177 extern interrupt_context_t *find_interrupt_context_by_id( 178 interrupt_context_list_t *, int); 179 extern interrupt_context_t *find_interrupt_context( 180 interrupt_context_list_t *, device_t *, int); 181 182 extern int register_interrupt_handler(device_t *, int, interrupt_handler_t *, 183 irq_code_t *); 184 extern int unregister_interrupt_handler(device_t *, int); 185 186 extern remote_handler_t *device_get_default_handler(device_t *); 187 extern int add_device_to_class(device_t *, const char *); 151 extern int ddf_fun_add_to_class(ddf_fun_t *, const char *); 188 152 189 153 #endif -
uspace/lib/drv/include/dev_iface.h
r5716e9a r76b5a95c 43 43 */ 44 44 45 struct d evice;45 struct ddf_fun; 46 46 47 47 /* … … 49 49 * devices driver. 50 50 */ 51 typedef void remote_iface_func_t(struct d evice*, void *, ipc_callid_t,51 typedef void remote_iface_func_t(struct ddf_fun *, void *, ipc_callid_t, 52 52 ipc_call_t *); 53 53 typedef remote_iface_func_t *remote_iface_func_ptr_t; 54 typedef void remote_handler_t(struct d evice*, ipc_callid_t, ipc_call_t *);54 typedef void remote_handler_t(struct ddf_fun *, ipc_callid_t, ipc_call_t *); 55 55 56 56 typedef struct { -
uspace/lib/drv/include/ops/char_dev.h
r5716e9a r76b5a95c 36 36 #define LIBDRV_OPS_CHAR_DEV_H_ 37 37 38 #include "../d river.h"38 #include "../ddf/driver.h" 39 39 40 40 typedef struct { 41 int (*read)(d evice_t *, char *, size_t);42 int (*write)(d evice_t *, char *, size_t);41 int (*read)(ddf_fun_t *, char *, size_t); 42 int (*write)(ddf_fun_t *, char *, size_t); 43 43 } char_dev_ops_t; 44 44 -
uspace/lib/drv/include/ops/hw_res.h
r5716e9a r76b5a95c 39 39 #include <sys/types.h> 40 40 41 #include "../d river.h"41 #include "../ddf/driver.h" 42 42 43 43 typedef struct { 44 hw_resource_list_t *(*get_resource_list)(d evice_t *);45 bool (*enable_interrupt)(d evice_t *);44 hw_resource_list_t *(*get_resource_list)(ddf_fun_t *); 45 bool (*enable_interrupt)(ddf_fun_t *); 46 46 } hw_res_ops_t; 47 47
Note:
See TracChangeset
for help on using the changeset viewer.