1 /* 2 * ustp - OpenWrt STP/RSTP/MSTP daemon 3 * Copyright (C) 2021 Felix Fietkau <nbd@nbd.name> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 7 * as published by the Free Software Foundation 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 */ 14 #include <pthread.h> 15 #include <string.h> 16 #include <stdlib.h> 17 18 #include <libubox/uloop.h> 19 #include <libubox/utils.h> 20 21 #include "worker.h" 22 #include "bridge_ctl.h" 23 #include "bridge_track.h" 24 #include "packet.h" 25 26 static pthread_t w_thread; 27 static pthread_mutex_t w_lock = PTHREAD_MUTEX_INITIALIZER; 28 static pthread_cond_t w_cond = PTHREAD_COND_INITIALIZER; 29 static LIST_HEAD(w_queue); 30 static struct uloop_timeout w_timer; 31 32 struct worker_queued_event { 33 struct list_head list; 34 struct worker_event ev; 35 }; 36 37 static struct worker_event *worker_next_event(void) 38 { 39 struct worker_queued_event *ev; 40 static struct worker_event ev_data; 41 42 pthread_mutex_lock(&w_lock); 43 while (list_empty(&w_queue)) 44 pthread_cond_wait(&w_cond, &w_lock); 45 46 ev = list_first_entry(&w_queue, struct worker_queued_event, list); 47 list_del(&ev->list); 48 pthread_mutex_unlock(&w_lock); 49 50 memcpy(&ev_data, &ev->ev, sizeof(ev_data)); 51 free(ev); 52 53 return &ev_data; 54 } 55 56 static void 57 handle_worker_event(struct worker_event *ev) 58 { 59 switch (ev->type) { 60 case WORKER_EV_ONE_SECOND: 61 bridge_one_second(); 62 break; 63 case WORKER_EV_BRIDGE_EVENT: 64 bridge_event_handler(); 65 break; 66 case WORKER_EV_RECV_PACKET: 67 packet_rcv(); 68 break; 69 case WORKER_EV_BRIDGE_ADD: 70 bridge_create(ev->bridge_idx, &ev->bridge_config); 71 break; 72 case WORKER_EV_BRIDGE_REMOVE: 73 bridge_delete(ev->bridge_idx); 74 break; 75 default: 76 return; 77 } 78 } 79 80 static void *worker_thread_fn(void *arg) 81 { 82 struct worker_event *ev; 83 84 while (1) { 85 ev = worker_next_event(); 86 if (ev->type == WORKER_EV_SHUTDOWN) 87 break; 88 89 handle_worker_event(ev); 90 } 91 92 return NULL; 93 } 94 95 static void worker_timer_cb(struct uloop_timeout *t) 96 { 97 struct worker_event ev = { 98 .type = WORKER_EV_ONE_SECOND, 99 }; 100 101 uloop_timeout_set(t, 1000); 102 worker_queue_event(&ev); 103 } 104 105 int worker_init(void) 106 { 107 w_timer.cb = worker_timer_cb; 108 uloop_timeout_set(&w_timer, 1000); 109 110 return pthread_create(&w_thread, NULL, worker_thread_fn, NULL); 111 } 112 113 void worker_cleanup(void) 114 { 115 struct worker_event ev = { 116 .type = WORKER_EV_SHUTDOWN, 117 }; 118 119 worker_queue_event(&ev); 120 pthread_join(w_thread, NULL); 121 } 122 123 void worker_queue_event(struct worker_event *ev) 124 { 125 struct worker_queued_event *evc; 126 127 evc = malloc(sizeof(*evc)); 128 memcpy(&evc->ev, ev, sizeof(*ev)); 129 130 pthread_mutex_lock(&w_lock); 131 list_add_tail(&evc->list, &w_queue); 132 pthread_mutex_unlock(&w_lock); 133 134 pthread_cond_signal(&w_cond); 135 } 136
This page was automatically generated by LXR 0.3.1. • OpenWrt