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