|
SASC-NG
DVBSoftCAM
|
00001 /* 00002 DVBLoopback 00003 Copyright Alan Nisota 2006 00004 00005 This file is part of DVBLoopback. 00006 00007 DVBLoopback is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 2 of the License, or 00010 (at your option) any later version. 00011 00012 DVBLoopback is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with DVBLoopback; if not, write to the Free Software 00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 #include <stdlib.h> 00022 #include <stdio.h> 00023 #include <fcntl.h> 00024 #include <pthread.h> 00025 #include <string.h> 00026 #include <getopt.h> 00027 #include <unistd.h> 00028 #include <sys/ioctl.h> 00029 #include <sched.h> 00030 #include <linux/dvb/frontend.h> 00031 #include <linux/dvb/dmx.h> 00032 #include "process_req.h" 00033 #include "plugin_getsid.h" 00034 #include "plugin_ringbuf.h" 00035 #include "msg_passing.h" 00036 00037 struct msgctrl { 00038 struct list_head msglist; 00039 struct list_head empty_queue; 00040 pthread_mutex_t mutex; 00041 pthread_cond_t cond; 00042 }; 00043 static struct msgctrl message_control[MSG_HIGH_PRIORITY+1]; 00044 00045 void msg_loop_init() 00046 { 00047 struct msgctrl *msgctrl; 00048 int priority; 00049 for (priority=0; priority <= MSG_HIGH_PRIORITY; priority++) { 00050 msgctrl = &message_control[priority]; 00051 bzero(msgctrl, sizeof(struct msgctrl)); 00052 INIT_LIST_HEAD(&msgctrl->msglist); 00053 INIT_LIST_HEAD(&msgctrl->empty_queue); 00054 pthread_mutex_init(&msgctrl->mutex, NULL); 00055 pthread_cond_init(&msgctrl->cond, NULL); 00056 } 00057 } 00058 void * msg_loop(void * arg) 00059 { 00060 unsigned long priority = (unsigned long)arg; 00061 struct list_head *ptr; 00062 struct msgctrl *msgctrl; 00063 00064 if (priority == MSG_HIGH_PRIORITY) { 00065 struct sched_param param; 00066 param.sched_priority = sched_get_priority_min(SCHED_FIFO); 00067 if(pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m)) { 00068 perror("sched_setscheduler"); 00069 } 00070 } 00071 if (priority > MSG_HIGH_PRIORITY) { 00072 tmprintf("MSG", "Invalid priority: %lu\n", priority); 00073 exit(-1); 00074 } 00075 00076 msgctrl = &message_control[priority]; 00077 pthread_mutex_lock(&msgctrl->mutex); 00078 while(1) { //main loop 00079 struct timespec ts = {0, 0}; 00080 ts.tv_sec = time(NULL) + 60*60; //1 hour 00081 while(1) { //iterate over all elements in queue 00082 struct msg *msg; 00083 time_t now = time(NULL); 00084 int orig_type; 00085 00086 //We don't need the 'safe' variant because we always break after removing 00087 //an element 00088 list_for_each(ptr, &msgctrl->msglist) { 00089 msg = list_entry(ptr, struct msg); 00090 if(now < msg->next_run) { 00091 if (msg->next_run < ts.tv_sec) 00092 ts.tv_sec = msg->next_run; 00093 continue; 00094 } 00095 list_del(&msg->list); 00096 break; 00097 } 00098 //If we've seen all elements on the queue, or the queue is empty, 00099 //we are done 00100 if(ptr == &msgctrl->msglist) 00101 break; 00102 pthread_mutex_unlock(&msgctrl->mutex); 00103 00104 if(msg->type == MSG_TERMINATE) 00105 return NULL; 00106 00107 orig_type = msg->type; 00108 list_for_each(ptr, &plugin_cmdlist) { 00109 struct plugin_cmd *cmd = list_entry(ptr, struct plugin_cmd); 00110 if(cmd->message) 00111 cmd->message(msg, priority); 00112 if(msg->type == MSG_PROCESSED) 00113 break; 00114 } 00115 if(msg->type != MSG_PROCESSED) { 00116 tmprintf("MSG", "Got unprocessed message type: %d\n", msg->type); 00117 } 00118 if (msg->recurring) { 00119 msg->next_run = time(NULL) + msg->recurring; 00120 msg->type = orig_type; 00121 if (msg->next_run < ts.tv_sec) 00122 ts.tv_sec = msg->next_run; 00123 pthread_mutex_lock(&msgctrl->mutex); 00124 list_add_tail(&msg->list, &msgctrl->msglist); 00125 } else { 00126 pthread_mutex_lock(&msgctrl->mutex); 00127 list_add(&msg->list, &msgctrl->empty_queue); 00128 } 00129 } 00130 pthread_cond_timedwait(&msgctrl->cond, &msgctrl->mutex, &ts); 00131 } 00132 } 00133 00134 void msg_remove_type_from_list(unsigned int priority, int type, int id, 00135 void (*cmd)(void *)) { 00136 struct list_head *ptr; 00137 struct msgctrl *msgctrl; 00138 00139 if (priority > MSG_HIGH_PRIORITY) 00140 return; 00141 msgctrl = &message_control[priority]; 00142 pthread_mutex_lock(&msgctrl->mutex); 00143 list_for_each(ptr, &msgctrl->msglist) { 00144 struct msg *msg = list_entry(ptr, struct msg); 00145 if (msg->type == type && msg->id == id) { 00146 list_del(&msg->list); 00147 if(cmd) 00148 cmd(msg->data); 00149 list_add(&msg->list, &msgctrl->empty_queue); 00150 break; 00151 } 00152 } 00153 pthread_mutex_unlock(&msgctrl->mutex); 00154 } 00155 00156 static struct msg *msg_add_type_to_list(unsigned int priority, int type, int id, 00157 int replace) { 00158 struct list_head *ptr; 00159 struct msg *msg; 00160 struct msgctrl *msgctrl; 00161 00162 msgctrl = &message_control[priority]; 00163 00164 if(replace) { 00165 //if a message of this type is already on the list 00166 list_for_each(ptr, &msgctrl->msglist) { 00167 msg = list_entry(ptr, struct msg); 00168 if (msg->type == type && msg->id == id) { 00169 return msg; 00170 } 00171 } 00172 } 00173 if(! list_empty(&msgctrl->empty_queue)) { 00174 msg = list_entry(msgctrl->empty_queue.next, struct msg); 00175 list_del(&msg->list); 00176 } else { 00177 msg = (struct msg *)malloc(sizeof(struct msg)); 00178 } 00179 list_add_tail(&msg->list, &msgctrl->msglist); 00180 msg->type = type; 00181 msg->id = id; 00182 msg->recurring = 0; 00183 msg->next_run = 0; 00184 return msg; 00185 } 00186 00187 void msg_send_replace(unsigned int priority, int type, int id, void *data, 00188 int delay, unsigned int flags) 00189 { 00190 struct msg *msg; 00191 struct msgctrl *msgctrl; 00192 00193 if (priority > MSG_HIGH_PRIORITY) 00194 return; 00195 msgctrl = &message_control[priority]; 00196 00197 pthread_mutex_lock(&msgctrl->mutex); 00198 msg = msg_add_type_to_list(priority, type, id, flags & MSG_REPLACE); 00199 msg->data = data; 00200 if (delay) 00201 msg->next_run = delay + time(NULL); 00202 if (flags & MSG_RECURRING) 00203 msg->recurring = delay; 00204 pthread_cond_signal(&msgctrl->cond); 00205 pthread_mutex_unlock(&msgctrl->mutex); 00206 } 00207 00208 void msg_terminate(unsigned int priority) 00209 { 00210 struct msg *msg; 00211 struct msgctrl *msgctrl; 00212 msgctrl = &message_control[priority]; 00213 pthread_mutex_lock(&msgctrl->mutex); 00214 if(! list_empty(&msgctrl->empty_queue)) { 00215 msg = list_entry(msgctrl->empty_queue.next, struct msg); 00216 list_del(&msg->list); 00217 } else { 00218 msg = (struct msg *)malloc(sizeof(struct msg)); 00219 } 00220 msg->type = MSG_TERMINATE; 00221 msg->id = 0; 00222 msg->recurring = 0; 00223 msg->next_run = 0; 00224 list_add(&msg->list, &msgctrl->msglist); 00225 pthread_cond_signal(&msgctrl->cond); 00226 pthread_mutex_unlock(&msgctrl->mutex); 00227 }