SASC-NG
DVBSoftCAM

msg_passing.c

Go to the documentation of this file.
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, &param)) {
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines