1/** 2 * \file 3 * \brief Handler function for asynchronous triggers sent by server. 4 */ 5 6/* 7 * Copyright (c) 2011, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <stdio.h> 16 17#include <barrelfish/barrelfish.h> 18#include <barrelfish/threads.h> 19 20#include <if/octopus_defs.h> 21#include <if/octopus_thc.h> 22 23#include <octopus/init.h> 24#include <octopus/getset.h> 25#include <octopus/trigger.h> 26 27#include "handler.h" 28#include "common.h" 29 30void trigger_handler(struct octopus_binding* b, octopus_trigger_id_t id, 31 uint64_t t, octopus_mode_t mode, const char* record, uint64_t st) 32{ 33 assert(t != 0); 34 35 // XXX: The casting to uintptr_t is for 32-bit archs 36 trigger_handler_fn trigger_fn = (trigger_handler_fn) (uintptr_t)t; 37 void* state = (void*) (uintptr_t)st; 38 39 if (trigger_fn != NULL) { 40 trigger_fn(mode, record, state); 41 } 42 else { 43 fprintf(stderr, "Incoming trigger(%"PRIu64") for %s with unset handler function.", 44 id, record); 45 } 46} 47 48octopus_trigger_t oct_mktrigger(errval_t in_case, octopus_binding_type_t send_to, 49 octopus_mode_t mode, trigger_handler_fn fn, void* state) 50{ 51 return (octopus_trigger_t) { 52 .in_case = in_case, 53 .m = mode, 54 .send_to = send_to, 55 // TODO: bad uint64_t here! 56 .trigger = (uint64_t)(uintptr_t) fn, 57 .st = (uint64_t)(uintptr_t) state 58 }; 59} 60 61/** 62 * \brief Removes a trigger in the octopus server. 63 * 64 * In any case a valid watch id is specified this 65 * causes a trigger event to be sent with the 66 * OCT_REMOVED flag set. After this event it's safe 67 * to clean up any memory associated with the event handler. 68 * 69 * \param trigger_id ID of trigger we want to remove 70 * 71 * \retval SYS_ERR_OK 72 * \retval OCT_INVALID_ID 73 */ 74errval_t oct_remove_trigger(octopus_trigger_id_t trigger_id) 75{ 76 errval_t err = SYS_ERR_OK; 77 struct octopus_thc_client_binding_t* cl = oct_get_thc_client(); 78 assert(cl != NULL); 79 80 errval_t error_code; 81 err = cl->call_seq.remove_trigger(cl, trigger_id, &error_code); 82 if (err_is_ok(err)) { 83 err = error_code; 84 } 85 86 return err; 87} 88 89/** 90 * Watches for a query of records and calls the trigger function for 91 * all records found and subsequent records registered. 92 * 93 * \param[in] query Records to watch for. 94 * \param[in] event_handler Handler function to call. 95 * \param[in] state Additional state for handler function 96 * \param[out] tid Trigger id. 97 * \retval SYS_ERR_OK Trigger registered, handler fn called for all 98 * current records. 99 */ 100errval_t oct_trigger_existing_and_watch(const char* query, 101 trigger_handler_fn event_handler, void* state, 102 octopus_trigger_id_t* tid) 103{ 104 char** names = NULL; 105 char* record = NULL; // freed by cpu_change_event 106 size_t len = 0; 107 octopus_trigger_t t = oct_mktrigger(0, octopus_BINDING_EVENT, 108 TRIGGER_ALWAYS, event_handler, state); 109 110 // Get current cores registered in system 111 struct octopus_thc_client_binding_t* rpc = oct_get_thc_client(); 112 113 struct octopus_get_names_response__rx_args reply; 114 errval_t err = rpc->call_seq.get_names(rpc, query, 115 t, reply.output, &reply.tid, &reply.error_code); 116 if (err_is_fail(err)) { 117 goto out; 118 } 119 err = reply.error_code; 120 121 switch(err_no(err)) { 122 case SYS_ERR_OK: 123 err = oct_parse_names(reply.output, &names, &len); 124 if (err_is_fail(err)) { 125 goto out; 126 } 127 128 for (size_t i=0; i < len; i++) { 129 err = oct_get(&record, names[i]); 130 131 switch (err_no(err)) { 132 case SYS_ERR_OK: 133 event_handler(OCT_ON_SET, record, state); 134 break; 135 136 case OCT_ERR_NO_RECORD: 137 break; 138 139 default: 140 DEBUG_ERR(err, "Unable to retrieve core record for %s", names[i]); 141 break; 142 } 143 } 144 break; 145 case OCT_ERR_NO_RECORD: 146 err = SYS_ERR_OK; // Overwrite (trigger is set) 147 break; 148 149 default: 150 // Do nothing (wait for trigger) 151 break; 152 } 153 154 // Return trigger id to caller, if requested 155 if (tid) { 156 *tid = reply.tid; 157 } 158 159out: 160 oct_free_names(names, len); 161 162 return err; 163} 164