Navigation


source: freeDiameter/libfdcore/events.c

Last change on this file was 1190:6a1042d8075b, checked in by Sebastien Decugis <sdecugis@freediameter.net>, 8 years ago

Replace FDEV_TERMINATE events with calls to fd_core_shutdown to handle the core state properly

File size: 7.0 KB
Line 
1/*********************************************************************************************************
2* Software License Agreement (BSD License)                                                               *
3* Author: Sebastien Decugis <sdecugis@freediameter.net>                                                  *
4*                                                                                                        *
5* Copyright (c) 2013, WIDE Project and NICT                                                              *
6* All rights reserved.                                                                                   *
7*                                                                                                        *
8* Redistribution and use of this software in source and binary forms, with or without modification, are  *
9* permitted provided that the following conditions are met:                                              *
10*                                                                                                        *
11* * Redistributions of source code must retain the above                                                 *
12*   copyright notice, this list of conditions and the                                                    *
13*   following disclaimer.                                                                                *
14*                                                                                                        *
15* * Redistributions in binary form must reproduce the above                                              *
16*   copyright notice, this list of conditions and the                                                    *
17*   following disclaimer in the documentation and/or other                                               *
18*   materials provided with the distribution.                                                            *
19*                                                                                                        *
20* * Neither the name of the WIDE Project or NICT nor the                                                 *
21*   names of its contributors may be used to endorse or                                                  *
22*   promote products derived from this software without                                                  *
23*   specific prior written permission of WIDE Project and                                                *
24*   NICT.                                                                                                *
25*                                                                                                        *
26* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
27* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
28* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
29* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT     *
30* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS    *
31* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
32* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
33* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                                                             *
34*********************************************************************************************************/
35
36#include "fdcore-internal.h"
37
38/* Events are a subset of fifo queues, with a known type */
39
40int fd_event_send(struct fifo *queue, int code, size_t datasz, void * data)
41{
42        struct fd_event * ev;
43        CHECK_MALLOC( ev = malloc(sizeof(struct fd_event)) );
44        ev->code = code;
45        ev->size = datasz;
46        ev->data = data;
47        CHECK_FCT( fd_fifo_post(queue, &ev) );
48        return 0;
49}
50
51int fd_event_get(struct fifo *queue, int *code, size_t *datasz, void ** data)
52{
53        struct fd_event * ev;
54        CHECK_FCT( fd_fifo_get(queue, &ev) );
55        if (code)
56                *code = ev->code;
57        if (datasz)
58                *datasz = ev->size;
59        if (data)
60                *data = ev->data;
61        free(ev);
62        return 0;
63}
64
65int fd_event_timedget(struct fifo *queue, struct timespec * timeout, int timeoutcode, int *code, size_t *datasz, void ** data)
66{
67        struct fd_event * ev;
68        int ret = 0;
69        ret = fd_fifo_timedget(queue, &ev, timeout);
70        if (ret == ETIMEDOUT) {
71                if (code)
72                        *code = timeoutcode;
73                if (datasz)
74                        *datasz = 0;
75                if (data)
76                        *data = NULL;
77        } else {
78                CHECK_FCT( ret );
79                if (code)
80                        *code = ev->code;
81                if (datasz)
82                        *datasz = ev->size;
83                if (data)
84                        *data = ev->data;
85                free(ev);
86        }
87        return 0;
88}
89
90void fd_event_destroy(struct fifo **queue, void (*free_cb)(void * data))
91{
92        struct fd_event * ev;
93        /* Purge all events, and free the associated data if any */
94        while (fd_fifo_tryget( *queue, &ev ) == 0) {
95                (*free_cb)(ev->data);
96                free(ev);
97        }
98        CHECK_FCT_DO( fd_fifo_del(queue), /* continue */ );
99        return ;
100} 
101
102const char * fd_ev_str(int event)
103{
104        switch (event) {
105        #define case_str( _val )\
106                case _val : return #_val
107                case_str(FDEV_TERMINATE_INT);
108                case_str(FDEV_TRIGGER);
109               
110                default:
111                        TRACE_DEBUG(FULL, "Unknown event : %d", event);
112                        return "Unknown event";
113        }
114}
115
116/**********************************************************************/
117/* Trigged events */
118/* This allows extensions to register for / send triggers to other extensions */
119/* It is used for example for users interactions (through signals or ...) */
120
121/* Because the number of triggers is not expected to grow, we use a simple ordered chained list */
122static pthread_rwlock_t trig_rwl = PTHREAD_RWLOCK_INITIALIZER;
123static struct fd_list   trig_list = FD_LIST_INITIALIZER(trig_list); /* The list of triggers ordered by trigger value */
124struct trig_item {
125        struct fd_list  chain;
126        int             trig_value;
127        const char *    trig_module;
128        void            (*cb)(void);
129};     
130
131/* Add a new entry in the trigger list */
132int fd_event_trig_regcb(int trigger_val, const char * module, void (*cb)(void))
133{
134        struct trig_item * ti;
135        struct fd_list * li;
136       
137        TRACE_ENTRY("%d %p %p", trigger_val, module, cb);
138        CHECK_PARAMS( trigger_val && cb );
139       
140        /* Create a new trig_item */
141        CHECK_MALLOC( ti = malloc(sizeof(struct trig_item)) );
142        memset(ti, 0, sizeof(struct trig_item));
143        fd_list_init(&ti->chain, ti);
144        ti->trig_value = trigger_val;
145        ti->trig_module = module;
146        ti->cb = cb;
147       
148        /* Now insert in the list */
149        CHECK_POSIX( pthread_rwlock_wrlock(&trig_rwl) );
150       
151        for (li = trig_list.next; li != &trig_list; li = li->next) {
152                struct trig_item *t = li->o;
153                if (t->trig_value >= trigger_val)
154                        break;
155        }
156       
157        fd_list_insert_before(li, &ti->chain);
158       
159        CHECK_POSIX( pthread_rwlock_unlock(&trig_rwl) );
160
161        return 0;
162}
163
164DECLARE_FD_DUMP_PROTOTYPE(fd_event_trig_dump)
165{
166        struct fd_list * li;
167        FD_DUMP_HANDLE_OFFSET();
168       
169        CHECK_POSIX_DO( pthread_rwlock_rdlock(&trig_rwl),  );
170       
171        for (li = trig_list.next; li != &trig_list; li = li->next) {
172                struct trig_item *t = li->o;
173                CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{signal:%d}'%s'->%p ", t->trig_value, t->trig_module, t->cb), break);
174        }
175       
176        CHECK_POSIX_DO( pthread_rwlock_unlock(&trig_rwl),  );
177        return *buf;
178}
179
180static void *call_cb_detached(void * arg)
181{
182        void (*cb)(void) = arg;
183        fd_log_threadname("Trig'd callback thread");
184        TRACE_ENTRY("%p", arg);
185        (*cb)();
186        TRACE_DEBUG(ANNOYING, "Callback %p completed", cb);
187        return NULL;
188}
189
190int fd_event_trig_call_cb(int trigger_val)
191{
192        struct fd_list * li;
193        pthread_attr_t detached;
194        pthread_t th;
195       
196        CHECK_POSIX( pthread_attr_init(&detached) );
197        CHECK_POSIX( pthread_attr_setdetachstate(&detached, PTHREAD_CREATE_DETACHED) );
198       
199        CHECK_POSIX( pthread_rwlock_rdlock(&trig_rwl)  );
200       
201        for (li = trig_list.next; li != &trig_list; li = li->next) {
202                struct trig_item *t = li->o;
203                if (t->trig_value == trigger_val) {
204                        TRACE_DEBUG(FULL, "Trigger %d: Calling %p in %s", t->trig_value, t->cb, t->trig_module);
205                        CHECK_POSIX_DO( pthread_create( &th, &detached, call_cb_detached, t->cb ), break );
206                }
207                if (t->trig_value > trigger_val)
208                        break;
209        }
210       
211        CHECK_POSIX( pthread_rwlock_unlock(&trig_rwl)  );
212       
213        return 0;
214}
215
216int fd_event_trig_fini(void) {
217       
218        TRACE_ENTRY("");
219       
220        CHECK_POSIX( pthread_rwlock_wrlock(&trig_rwl) );
221       
222        while (!FD_IS_LIST_EMPTY(&trig_list)) {
223                struct fd_list * li = trig_list.next;
224                fd_list_unlink(li);
225                free(li);
226        }
227       
228        CHECK_POSIX( pthread_rwlock_unlock(&trig_rwl) );
229       
230        return 0;
231}
Note: See TracBrowser for help on using the repository browser.