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