1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13/*- import 'helpers/error.c' as error with context -*/ 14 15#include <camkes/error.h> 16#include <camkes/tls.h> 17#include <limits.h> 18#include <sel4/sel4.h> 19#include <stdbool.h> 20#include <stdlib.h> 21#include <sync/bin_sem_bare.h> 22#include <sync/sem-bare.h> 23#include <utils/util.h> 24 25/*? macros.show_includes(me.instance.type.includes) ?*/ 26 27/* Interface-specific error handling. */ 28/*- set error_handler = '%s_error_handler' % me.interface.name -*/ 29/*? error.make_error_handler(me.interface.name, error_handler) ?*/ 30 31/*- set id = me.parent.to_ends.index(me) -*/ 32 33/*- set ep = alloc('ep_%d' % id, seL4_EndpointObject, read=True) -*/ 34/*- set handoff = alloc('handoff_%d' % id, seL4_EndpointObject, label=me.instance.name, read=True, write=True) -*/ 35static volatile int handoff_value; 36 37char to_/*? id ?*/_/*? me.interface.name ?*/_data[ROUND_UP_UNSAFE(sizeof(int), PAGE_SIZE_4K)] 38 ALIGN(4096) 39 SECTION("align_12bit"); 40static volatile int *value = (volatile int*)to_/*? id ?*/_/*? me.interface.name ?*/_data; 41/*? register_shared_variable('%s_%d_data' % (me.parent.name, id), 'to_%d_%s_data' % (id, me.interface.name), 4096, perm='RW') ?*/ 42 43/*- set lock = alloc('lock_%d' % id, seL4_NotificationObject, label=me.instance.name, read=True, write=True) -*/ 44static volatile int lock_count = 1; 45 46static int lock(void) { 47 int result = sync_bin_sem_bare_wait(/*? lock ?*/, &lock_count); 48 __sync_synchronize(); 49 return result; 50} 51 52static int unlock(void) { 53 __sync_synchronize(); 54 return sync_bin_sem_bare_post(/*? lock ?*/, &lock_count); 55} 56 57static void (*volatile callback)(void*); 58static void *callback_arg; 59 60int /*? me.interface.name ?*/__run(void) { 61 while (true) { 62restart:; 63 int result UNUSED = sync_sem_bare_wait(/*? ep ?*/, value); 64 ERR_IF(result != 0, /*? error_handler ?*/, ((camkes_error_t){ 65 .type = CE_OVERFLOW, 66 .instance = "/*? me.instance.name ?*/", 67 .interface = "/*? me.interface.name ?*/", 68 .description = "waiting on semaphore failed", 69 }), ({ 70 goto restart; 71 })); 72 73 if (lock() != 0) { 74 ERR(/*? error_handler ?*/, ((camkes_error_t){ 75 .type = CE_OVERFLOW, 76 .instance = "/*? me.instance.name ?*/", 77 .interface = "/*? me.interface.name ?*/", 78 .description = "lock acquisition failed due to too many outstanding lock holders", 79 }), ({ 80 goto restart; 81 })); 82 } 83 84 void (*cb)(void*) = callback; 85 callback = NULL; 86 void *arg = callback_arg; 87 88 if (cb == NULL) { 89 ERR_IF(handoff_value == INT_MAX, /*? error_handler ?*/, ((camkes_error_t){ 90 .type = CE_OVERFLOW, 91 .instance = "/*? me.instance.name ?*/", 92 .interface = "/*? me.interface.name ?*/", 93 .description = "handoff to internal endpoint not possible due to counter overflow", 94 }), ({ 95 int result UNUSED = unlock(); 96 assert(result == 0); 97 goto restart; 98 })); 99 sync_sem_bare_post(/*? handoff ?*/, &handoff_value); 100 } 101 102 result = unlock(); 103 assert(result == 0); 104 105 if (cb != NULL) { 106 cb(arg); 107 } 108 } 109} 110 111static int poll(void) { 112 return sync_sem_bare_trywait(/*? handoff ?*/, &handoff_value) == 0; 113} 114 115int /*? me.interface.name ?*/_poll(void) { 116 return poll(); 117} 118 119void /*? me.interface.name ?*/_wait(void) { 120#ifndef CONFIG_KERNEL_MCS 121 camkes_protect_reply_cap(); 122#endif 123 if (sync_sem_bare_wait(/*? handoff ?*/, &handoff_value) != 0) { 124 ERR(/*? error_handler ?*/, ((camkes_error_t){ 125 .type = CE_OVERFLOW, 126 .instance = "/*? me.instance.name ?*/", 127 .interface = "/*? me.interface.name ?*/", 128 .description = "wait failed due to future counter overflow", 129 }), ({ 130 return; 131 })); 132 } 133} 134 135int /*? me.interface.name ?*/_reg_callback(void (*cb)(void*), void *arg) { 136 137 if (poll()) { 138 cb(arg); 139 return 0; 140 } 141 142 if (lock() != 0) { 143 return -1; 144 } 145 146 if (poll()) { 147 int result UNUSED = unlock(); 148 assert(result == 0); 149 cb(arg); 150 return 0; 151 152 } else if (callback != NULL) { 153 int result UNUSED = unlock(); 154 assert(result == 0); 155 return -1; 156 157 } else { 158 callback = cb; 159 callback_arg = arg; 160 int result UNUSED = unlock(); 161 assert(result == 0); 162 return 0; 163 } 164} 165