xref: /minix3/minix/lib/liblwip/dist/src/apps/snmp/snmp_threadsync.c (revision 5d5fbe79c1b60734f34c69330aec5496644e8651)
1*5d5fbe79SDavid van Moolenbroek /**
2*5d5fbe79SDavid van Moolenbroek  * @file
3*5d5fbe79SDavid van Moolenbroek  * SNMP thread synchronization implementation.
4*5d5fbe79SDavid van Moolenbroek  */
5*5d5fbe79SDavid van Moolenbroek 
6*5d5fbe79SDavid van Moolenbroek /*
7*5d5fbe79SDavid van Moolenbroek  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
8*5d5fbe79SDavid van Moolenbroek  * All rights reserved.
9*5d5fbe79SDavid van Moolenbroek  *
10*5d5fbe79SDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without modification,
11*5d5fbe79SDavid van Moolenbroek  * are permitted provided that the following conditions are met:
12*5d5fbe79SDavid van Moolenbroek  *
13*5d5fbe79SDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright notice,
14*5d5fbe79SDavid van Moolenbroek  *    this list of conditions and the following disclaimer.
15*5d5fbe79SDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright notice,
16*5d5fbe79SDavid van Moolenbroek  *    this list of conditions and the following disclaimer in the documentation
17*5d5fbe79SDavid van Moolenbroek  *    and/or other materials provided with the distribution.
18*5d5fbe79SDavid van Moolenbroek  * 3. The name of the author may not be used to endorse or promote products
19*5d5fbe79SDavid van Moolenbroek  *    derived from this software without specific prior written permission.
20*5d5fbe79SDavid van Moolenbroek  *
21*5d5fbe79SDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
22*5d5fbe79SDavid van Moolenbroek  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23*5d5fbe79SDavid van Moolenbroek  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
24*5d5fbe79SDavid van Moolenbroek  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25*5d5fbe79SDavid van Moolenbroek  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26*5d5fbe79SDavid van Moolenbroek  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27*5d5fbe79SDavid van Moolenbroek  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28*5d5fbe79SDavid van Moolenbroek  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29*5d5fbe79SDavid van Moolenbroek  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
30*5d5fbe79SDavid van Moolenbroek  * OF SUCH DAMAGE.
31*5d5fbe79SDavid van Moolenbroek  *
32*5d5fbe79SDavid van Moolenbroek  * Author: Dirk Ziegelmeier <dziegel@gmx.de>
33*5d5fbe79SDavid van Moolenbroek  */
34*5d5fbe79SDavid van Moolenbroek 
35*5d5fbe79SDavid van Moolenbroek #include "lwip/apps/snmp_opts.h"
36*5d5fbe79SDavid van Moolenbroek 
37*5d5fbe79SDavid van Moolenbroek #if LWIP_SNMP && (NO_SYS == 0) /* don't build if not configured for use in lwipopts.h */
38*5d5fbe79SDavid van Moolenbroek 
39*5d5fbe79SDavid van Moolenbroek #include "lwip/apps/snmp_threadsync.h"
40*5d5fbe79SDavid van Moolenbroek #include "lwip/apps/snmp_core.h"
41*5d5fbe79SDavid van Moolenbroek #include "lwip/sys.h"
42*5d5fbe79SDavid van Moolenbroek #include <string.h>
43*5d5fbe79SDavid van Moolenbroek 
44*5d5fbe79SDavid van Moolenbroek static void
call_synced_function(struct threadsync_data * call_data,snmp_threadsync_called_fn fn)45*5d5fbe79SDavid van Moolenbroek call_synced_function(struct threadsync_data *call_data, snmp_threadsync_called_fn fn)
46*5d5fbe79SDavid van Moolenbroek {
47*5d5fbe79SDavid van Moolenbroek   sys_mutex_lock(&call_data->threadsync_node->instance->sem_usage_mutex);
48*5d5fbe79SDavid van Moolenbroek   call_data->threadsync_node->instance->sync_fn(fn, call_data);
49*5d5fbe79SDavid van Moolenbroek   sys_sem_wait(&call_data->threadsync_node->instance->sem);
50*5d5fbe79SDavid van Moolenbroek   sys_mutex_unlock(&call_data->threadsync_node->instance->sem_usage_mutex);
51*5d5fbe79SDavid van Moolenbroek }
52*5d5fbe79SDavid van Moolenbroek 
53*5d5fbe79SDavid van Moolenbroek static void
threadsync_get_value_synced(void * ctx)54*5d5fbe79SDavid van Moolenbroek threadsync_get_value_synced(void *ctx)
55*5d5fbe79SDavid van Moolenbroek {
56*5d5fbe79SDavid van Moolenbroek   struct threadsync_data *call_data = (struct threadsync_data*)ctx;
57*5d5fbe79SDavid van Moolenbroek 
58*5d5fbe79SDavid van Moolenbroek   call_data->retval.s16 = call_data->proxy_instance.get_value(&call_data->proxy_instance, call_data->arg1.value);
59*5d5fbe79SDavid van Moolenbroek 
60*5d5fbe79SDavid van Moolenbroek   sys_sem_signal(&call_data->threadsync_node->instance->sem);
61*5d5fbe79SDavid van Moolenbroek }
62*5d5fbe79SDavid van Moolenbroek 
63*5d5fbe79SDavid van Moolenbroek static s16_t
threadsync_get_value(struct snmp_node_instance * instance,void * value)64*5d5fbe79SDavid van Moolenbroek threadsync_get_value(struct snmp_node_instance* instance, void* value)
65*5d5fbe79SDavid van Moolenbroek {
66*5d5fbe79SDavid van Moolenbroek   struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr;
67*5d5fbe79SDavid van Moolenbroek 
68*5d5fbe79SDavid van Moolenbroek   call_data->arg1.value = value;
69*5d5fbe79SDavid van Moolenbroek   call_synced_function(call_data, threadsync_get_value_synced);
70*5d5fbe79SDavid van Moolenbroek 
71*5d5fbe79SDavid van Moolenbroek   return call_data->retval.s16;
72*5d5fbe79SDavid van Moolenbroek }
73*5d5fbe79SDavid van Moolenbroek 
74*5d5fbe79SDavid van Moolenbroek static void
threadsync_set_test_synced(void * ctx)75*5d5fbe79SDavid van Moolenbroek threadsync_set_test_synced(void *ctx)
76*5d5fbe79SDavid van Moolenbroek {
77*5d5fbe79SDavid van Moolenbroek   struct threadsync_data *call_data = (struct threadsync_data*)ctx;
78*5d5fbe79SDavid van Moolenbroek 
79*5d5fbe79SDavid van Moolenbroek   call_data->retval.err = call_data->proxy_instance.set_test(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value);
80*5d5fbe79SDavid van Moolenbroek 
81*5d5fbe79SDavid van Moolenbroek   sys_sem_signal(&call_data->threadsync_node->instance->sem);
82*5d5fbe79SDavid van Moolenbroek }
83*5d5fbe79SDavid van Moolenbroek 
84*5d5fbe79SDavid van Moolenbroek static snmp_err_t
threadsync_set_test(struct snmp_node_instance * instance,u16_t len,void * value)85*5d5fbe79SDavid van Moolenbroek threadsync_set_test(struct snmp_node_instance* instance, u16_t len, void *value)
86*5d5fbe79SDavid van Moolenbroek {
87*5d5fbe79SDavid van Moolenbroek   struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr;
88*5d5fbe79SDavid van Moolenbroek 
89*5d5fbe79SDavid van Moolenbroek   call_data->arg1.value = value;
90*5d5fbe79SDavid van Moolenbroek   call_data->arg2.len = len;
91*5d5fbe79SDavid van Moolenbroek   call_synced_function(call_data, threadsync_set_test_synced);
92*5d5fbe79SDavid van Moolenbroek 
93*5d5fbe79SDavid van Moolenbroek   return call_data->retval.err;
94*5d5fbe79SDavid van Moolenbroek }
95*5d5fbe79SDavid van Moolenbroek 
96*5d5fbe79SDavid van Moolenbroek static void
threadsync_set_value_synced(void * ctx)97*5d5fbe79SDavid van Moolenbroek threadsync_set_value_synced(void *ctx)
98*5d5fbe79SDavid van Moolenbroek {
99*5d5fbe79SDavid van Moolenbroek   struct threadsync_data *call_data = (struct threadsync_data*)ctx;
100*5d5fbe79SDavid van Moolenbroek 
101*5d5fbe79SDavid van Moolenbroek   call_data->retval.err = call_data->proxy_instance.set_value(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value);
102*5d5fbe79SDavid van Moolenbroek 
103*5d5fbe79SDavid van Moolenbroek   sys_sem_signal(&call_data->threadsync_node->instance->sem);
104*5d5fbe79SDavid van Moolenbroek }
105*5d5fbe79SDavid van Moolenbroek 
106*5d5fbe79SDavid van Moolenbroek static snmp_err_t
threadsync_set_value(struct snmp_node_instance * instance,u16_t len,void * value)107*5d5fbe79SDavid van Moolenbroek threadsync_set_value(struct snmp_node_instance* instance, u16_t len, void *value)
108*5d5fbe79SDavid van Moolenbroek {
109*5d5fbe79SDavid van Moolenbroek   struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr;
110*5d5fbe79SDavid van Moolenbroek 
111*5d5fbe79SDavid van Moolenbroek   call_data->arg1.value = value;
112*5d5fbe79SDavid van Moolenbroek   call_data->arg2.len = len;
113*5d5fbe79SDavid van Moolenbroek   call_synced_function(call_data, threadsync_set_value_synced);
114*5d5fbe79SDavid van Moolenbroek 
115*5d5fbe79SDavid van Moolenbroek   return call_data->retval.err;
116*5d5fbe79SDavid van Moolenbroek }
117*5d5fbe79SDavid van Moolenbroek 
118*5d5fbe79SDavid van Moolenbroek static void
threadsync_release_instance_synced(void * ctx)119*5d5fbe79SDavid van Moolenbroek threadsync_release_instance_synced(void* ctx)
120*5d5fbe79SDavid van Moolenbroek {
121*5d5fbe79SDavid van Moolenbroek   struct threadsync_data *call_data = (struct threadsync_data*)ctx;
122*5d5fbe79SDavid van Moolenbroek 
123*5d5fbe79SDavid van Moolenbroek   call_data->proxy_instance.release_instance(&call_data->proxy_instance);
124*5d5fbe79SDavid van Moolenbroek 
125*5d5fbe79SDavid van Moolenbroek   sys_sem_signal(&call_data->threadsync_node->instance->sem);
126*5d5fbe79SDavid van Moolenbroek }
127*5d5fbe79SDavid van Moolenbroek 
128*5d5fbe79SDavid van Moolenbroek static void
threadsync_release_instance(struct snmp_node_instance * instance)129*5d5fbe79SDavid van Moolenbroek threadsync_release_instance(struct snmp_node_instance *instance)
130*5d5fbe79SDavid van Moolenbroek {
131*5d5fbe79SDavid van Moolenbroek   struct threadsync_data *call_data = (struct threadsync_data*)instance->reference.ptr;
132*5d5fbe79SDavid van Moolenbroek 
133*5d5fbe79SDavid van Moolenbroek   if (call_data->proxy_instance.release_instance != NULL) {
134*5d5fbe79SDavid van Moolenbroek     call_synced_function(call_data, threadsync_release_instance_synced);
135*5d5fbe79SDavid van Moolenbroek   }
136*5d5fbe79SDavid van Moolenbroek }
137*5d5fbe79SDavid van Moolenbroek 
138*5d5fbe79SDavid van Moolenbroek static void
get_instance_synced(void * ctx)139*5d5fbe79SDavid van Moolenbroek get_instance_synced(void* ctx)
140*5d5fbe79SDavid van Moolenbroek {
141*5d5fbe79SDavid van Moolenbroek   struct threadsync_data *call_data   = (struct threadsync_data*)ctx;
142*5d5fbe79SDavid van Moolenbroek   const struct snmp_leaf_node *leaf   = (const struct snmp_leaf_node*)(const void*)call_data->proxy_instance.node;
143*5d5fbe79SDavid van Moolenbroek 
144*5d5fbe79SDavid van Moolenbroek   call_data->retval.err = leaf->get_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance);
145*5d5fbe79SDavid van Moolenbroek 
146*5d5fbe79SDavid van Moolenbroek   sys_sem_signal(&call_data->threadsync_node->instance->sem);
147*5d5fbe79SDavid van Moolenbroek }
148*5d5fbe79SDavid van Moolenbroek 
149*5d5fbe79SDavid van Moolenbroek static void
get_next_instance_synced(void * ctx)150*5d5fbe79SDavid van Moolenbroek get_next_instance_synced(void* ctx)
151*5d5fbe79SDavid van Moolenbroek {
152*5d5fbe79SDavid van Moolenbroek   struct threadsync_data *call_data   = (struct threadsync_data*)ctx;
153*5d5fbe79SDavid van Moolenbroek   const struct snmp_leaf_node *leaf   = (const struct snmp_leaf_node*)(const void*)call_data->proxy_instance.node;
154*5d5fbe79SDavid van Moolenbroek 
155*5d5fbe79SDavid van Moolenbroek   call_data->retval.err = leaf->get_next_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance);
156*5d5fbe79SDavid van Moolenbroek 
157*5d5fbe79SDavid van Moolenbroek   sys_sem_signal(&call_data->threadsync_node->instance->sem);
158*5d5fbe79SDavid van Moolenbroek }
159*5d5fbe79SDavid van Moolenbroek 
160*5d5fbe79SDavid van Moolenbroek static snmp_err_t
do_sync(const u32_t * root_oid,u8_t root_oid_len,struct snmp_node_instance * instance,snmp_threadsync_called_fn fn)161*5d5fbe79SDavid van Moolenbroek do_sync(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance, snmp_threadsync_called_fn fn)
162*5d5fbe79SDavid van Moolenbroek {
163*5d5fbe79SDavid van Moolenbroek   const struct snmp_threadsync_node *threadsync_node = (const struct snmp_threadsync_node*)(const void*)instance->node;
164*5d5fbe79SDavid van Moolenbroek   struct threadsync_data *call_data = &threadsync_node->instance->data;
165*5d5fbe79SDavid van Moolenbroek 
166*5d5fbe79SDavid van Moolenbroek   if (threadsync_node->node.node.oid != threadsync_node->target->node.oid) {
167*5d5fbe79SDavid van Moolenbroek     LWIP_DEBUGF(SNMP_DEBUG, ("Sync node OID does not match target node OID"));
168*5d5fbe79SDavid van Moolenbroek     return SNMP_ERR_NOSUCHINSTANCE;
169*5d5fbe79SDavid van Moolenbroek   }
170*5d5fbe79SDavid van Moolenbroek 
171*5d5fbe79SDavid van Moolenbroek   memset(&call_data->proxy_instance, 0, sizeof(call_data->proxy_instance));
172*5d5fbe79SDavid van Moolenbroek 
173*5d5fbe79SDavid van Moolenbroek   instance->reference.ptr = call_data;
174*5d5fbe79SDavid van Moolenbroek   snmp_oid_assign(&call_data->proxy_instance.instance_oid, instance->instance_oid.id, instance->instance_oid.len);
175*5d5fbe79SDavid van Moolenbroek 
176*5d5fbe79SDavid van Moolenbroek   call_data->proxy_instance.node = &threadsync_node->target->node;
177*5d5fbe79SDavid van Moolenbroek   call_data->threadsync_node     = threadsync_node;
178*5d5fbe79SDavid van Moolenbroek 
179*5d5fbe79SDavid van Moolenbroek   call_data->arg1.root_oid       = root_oid;
180*5d5fbe79SDavid van Moolenbroek   call_data->arg2.root_oid_len   = root_oid_len;
181*5d5fbe79SDavid van Moolenbroek   call_synced_function(call_data, fn);
182*5d5fbe79SDavid van Moolenbroek 
183*5d5fbe79SDavid van Moolenbroek   if (call_data->retval.err == SNMP_ERR_NOERROR) {
184*5d5fbe79SDavid van Moolenbroek     instance->access           = call_data->proxy_instance.access;
185*5d5fbe79SDavid van Moolenbroek     instance->asn1_type        = call_data->proxy_instance.asn1_type;
186*5d5fbe79SDavid van Moolenbroek     instance->release_instance = threadsync_release_instance;
187*5d5fbe79SDavid van Moolenbroek     instance->get_value        = (call_data->proxy_instance.get_value != NULL)? threadsync_get_value : NULL;
188*5d5fbe79SDavid van Moolenbroek     instance->set_value        = (call_data->proxy_instance.set_value != NULL)? threadsync_set_value : NULL;
189*5d5fbe79SDavid van Moolenbroek     instance->set_test         = (call_data->proxy_instance.set_test != NULL)?  threadsync_set_test  : NULL;
190*5d5fbe79SDavid van Moolenbroek     snmp_oid_assign(&instance->instance_oid, call_data->proxy_instance.instance_oid.id, call_data->proxy_instance.instance_oid.len);
191*5d5fbe79SDavid van Moolenbroek   }
192*5d5fbe79SDavid van Moolenbroek 
193*5d5fbe79SDavid van Moolenbroek   return call_data->retval.err;
194*5d5fbe79SDavid van Moolenbroek }
195*5d5fbe79SDavid van Moolenbroek 
196*5d5fbe79SDavid van Moolenbroek snmp_err_t
snmp_threadsync_get_instance(const u32_t * root_oid,u8_t root_oid_len,struct snmp_node_instance * instance)197*5d5fbe79SDavid van Moolenbroek snmp_threadsync_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
198*5d5fbe79SDavid van Moolenbroek {
199*5d5fbe79SDavid van Moolenbroek   return do_sync(root_oid, root_oid_len, instance, get_instance_synced);
200*5d5fbe79SDavid van Moolenbroek }
201*5d5fbe79SDavid van Moolenbroek 
202*5d5fbe79SDavid van Moolenbroek snmp_err_t
snmp_threadsync_get_next_instance(const u32_t * root_oid,u8_t root_oid_len,struct snmp_node_instance * instance)203*5d5fbe79SDavid van Moolenbroek snmp_threadsync_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance* instance)
204*5d5fbe79SDavid van Moolenbroek {
205*5d5fbe79SDavid van Moolenbroek   return do_sync(root_oid, root_oid_len, instance, get_next_instance_synced);
206*5d5fbe79SDavid van Moolenbroek }
207*5d5fbe79SDavid van Moolenbroek 
208*5d5fbe79SDavid van Moolenbroek /** Initializes thread synchronization instance */
snmp_threadsync_init(struct snmp_threadsync_instance * instance,snmp_threadsync_synchronizer_fn sync_fn)209*5d5fbe79SDavid van Moolenbroek void snmp_threadsync_init(struct snmp_threadsync_instance *instance, snmp_threadsync_synchronizer_fn sync_fn)
210*5d5fbe79SDavid van Moolenbroek {
211*5d5fbe79SDavid van Moolenbroek   err_t err = sys_mutex_new(&instance->sem_usage_mutex);
212*5d5fbe79SDavid van Moolenbroek   LWIP_ASSERT("Failed to set up mutex", err == ERR_OK);
213*5d5fbe79SDavid van Moolenbroek   err = sys_sem_new(&instance->sem, 0);
214*5d5fbe79SDavid van Moolenbroek   LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */
215*5d5fbe79SDavid van Moolenbroek   LWIP_ASSERT("Failed to set up semaphore", err == ERR_OK);
216*5d5fbe79SDavid van Moolenbroek   instance->sync_fn = sync_fn;
217*5d5fbe79SDavid van Moolenbroek }
218*5d5fbe79SDavid van Moolenbroek 
219*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_SNMP */
220