SASC
DVBSoftCAM

msg_passing.h File Reference

#include "list.h"

Go to the source code of this file.

Classes

struct  msg

Defines

#define MSG_PROCESSED   -1
#define MSG_TERMINATE   -2
#define MSG_LOW_PRIORITY   0
#define MSG_HIGH_PRIORITY   1
#define MSG_REPLACE   0x01
#define MSG_RECURRING   0x02
#define msg_send(a, b, c, d)   msg_send_replace(a,b,c,d,0,0)
#define msg_replace(a, b, c, d)   msg_send_replace(a,b,c,d,0,MSG_REPLACE)
#define msg_delayed(a, b, c, d, e, f)

Functions

void msg_loop_init ()
void * msg_loop (void *arg)
void msg_remove_type_from_list (unsigned int priority, int type, int id, void(*cmd)(void *msg))
void msg_send_replace (unsigned int priority, int type, int id, void *data, int delay, unsigned int flags)
void msg_terminate (unsigned int priority)

Define Documentation

#define msg_delayed (   a,
  b,
  c,
  d,
  e,
  f 
)
Value:
msg_send_replace(a,b,c,d,e, \
                                                  ((f)? MSG_RECURRING : 0)

Definition at line 31 of file msg_passing.h.

#define MSG_LOW_PRIORITY   0
#define MSG_PROCESSED   -1

Definition at line 5 of file msg_passing.h.

Referenced by msg_loop(), process_cam(), process_ffd(), and process_scan().

#define MSG_RECURRING   0x02

Definition at line 11 of file msg_passing.h.

Referenced by launch_cam(), launch_scan(), and msg_send_replace().

#define MSG_REPLACE   0x01

Definition at line 10 of file msg_passing.h.

Referenced by msg_send_replace().

#define msg_replace (   a,
  b,
  c,
  d 
)    msg_send_replace(a,b,c,d,0,MSG_REPLACE)
#define msg_send (   a,
  b,
  c,
  d 
)    msg_send_replace(a,b,c,d,0,0)

Definition at line 29 of file msg_passing.h.

Referenced by _SetCaDescr(), close_demux(), fe_close(), fe_tune(), read_sid(), and set_demux().

#define MSG_TERMINATE   -2

Definition at line 6 of file msg_passing.h.

Referenced by msg_loop(), and msg_terminate().


Function Documentation

void* msg_loop ( void *  arg)

Definition at line 58 of file msg_passing.c.

References cmd, msgctrl::cond, msgctrl::empty_queue, msg::list, list_add(), list_add_tail(), list_del(), list_entry, list_for_each, plugin_cmd::message, message_control, MSG_HIGH_PRIORITY, MSG_PROCESSED, MSG_TERMINATE, msgctrl::msglist, msgctrl::mutex, msg::next_run, NULL, plugin_cmdlist, msg::recurring, tmprintf(), and msg::type.

Referenced by main().

{
  unsigned long priority = (unsigned long)arg;
  struct list_head *ptr;
  struct msgctrl *msgctrl;

  if (priority == MSG_HIGH_PRIORITY) {
    struct sched_param param;
    param.sched_priority = sched_get_priority_min(SCHED_FIFO);
    if(pthread_setschedparam(pthread_self(), SCHED_FIFO, &param)) {
      perror("sched_setscheduler");
    }
  }
  if (priority > MSG_HIGH_PRIORITY) {
    tmprintf("MSG", "Invalid priority: %lu\n", priority);
    exit(-1);
  }

  msgctrl = &message_control[priority];
  pthread_mutex_lock(&msgctrl->mutex);
  while(1) { //main loop
    struct timespec ts = {0, 0};
    ts.tv_sec = time(NULL) + 60*60; //1 hour
    while(1) { //iterate over all elements in queue
      struct msg *msg;
      time_t now = time(NULL);
      int orig_type;

      //We don't need the 'safe' variant because we always break after removing
      //an element
      list_for_each(ptr, &msgctrl->msglist) {
        msg = list_entry(ptr, struct msg);
        if(now < msg->next_run) {
          if (msg->next_run < ts.tv_sec)
            ts.tv_sec = msg->next_run;
          continue;
        }
        list_del(&msg->list);
        break;
      }
      //If we've seen all elements on the queue, or the queue is empty,
      //we are done
      if(ptr == &msgctrl->msglist)
        break;
      pthread_mutex_unlock(&msgctrl->mutex);

      if(msg->type == MSG_TERMINATE)
        return NULL;

      orig_type = msg->type;
      list_for_each(ptr, &plugin_cmdlist) {
        struct plugin_cmd *cmd = list_entry(ptr, struct plugin_cmd);
        if(cmd->message)
          cmd->message(msg, priority);
        if(msg->type == MSG_PROCESSED)
          break;
      }
      if(msg->type != MSG_PROCESSED) {
        tmprintf("MSG", "Got unprocessed message type: %d\n", msg->type);
      }
      if (msg->recurring) {
        msg->next_run = time(NULL) + msg->recurring;
        msg->type = orig_type;
        if (msg->next_run < ts.tv_sec)
          ts.tv_sec = msg->next_run;
        pthread_mutex_lock(&msgctrl->mutex);
        list_add_tail(&msg->list, &msgctrl->msglist);
      } else {
        pthread_mutex_lock(&msgctrl->mutex);
        list_add(&msg->list, &msgctrl->empty_queue);
      }
    }
    pthread_cond_timedwait(&msgctrl->cond, &msgctrl->mutex, &ts);
  }
}
void msg_loop_init ( )

Definition at line 45 of file msg_passing.c.

References msgctrl::cond, msgctrl::empty_queue, INIT_LIST_HEAD, message_control, MSG_HIGH_PRIORITY, msgctrl::msglist, msgctrl::mutex, and NULL.

Referenced by main().

{
  struct msgctrl *msgctrl;
  int priority;
  for (priority=0; priority <= MSG_HIGH_PRIORITY; priority++) {
    msgctrl = &message_control[priority];
    bzero(msgctrl, sizeof(struct msgctrl));
    INIT_LIST_HEAD(&msgctrl->msglist);
    INIT_LIST_HEAD(&msgctrl->empty_queue);
    pthread_mutex_init(&msgctrl->mutex, NULL);
    pthread_cond_init(&msgctrl->cond, NULL);
  }
}
void msg_remove_type_from_list ( unsigned int  priority,
int  type,
int  id,
void(*)(void *msg)  cmd 
)
void msg_send_replace ( unsigned int  priority,
int  type,
int  id,
void *  data,
int  delay,
unsigned int  flags 
)

Definition at line 187 of file msg_passing.c.

References msgctrl::cond, data, msg::data, message_control, msg_add_type_to_list(), MSG_HIGH_PRIORITY, MSG_RECURRING, MSG_REPLACE, msgctrl::mutex, msg::next_run, NULL, and msg::recurring.

Referenced by launch_cam(), and launch_scan().

{
  struct msg *msg;
  struct msgctrl *msgctrl;

  if (priority > MSG_HIGH_PRIORITY)
    return;
  msgctrl = &message_control[priority];

  pthread_mutex_lock(&msgctrl->mutex);
  msg = msg_add_type_to_list(priority, type, id, flags & MSG_REPLACE);
  msg->data = data;
  if (delay)
    msg->next_run = delay + time(NULL);
  if (flags & MSG_RECURRING)
    msg->recurring = delay;
  pthread_cond_signal(&msgctrl->cond);
  pthread_mutex_unlock(&msgctrl->mutex);
}
void msg_terminate ( unsigned int  priority)

Definition at line 208 of file msg_passing.c.

References msgctrl::cond, msgctrl::empty_queue, msg::id, msg::list, list_add(), list_del(), list_empty(), list_entry, message_control, MSG_TERMINATE, msgctrl::msglist, msgctrl::mutex, list_head::next, msg::next_run, msg::recurring, and msg::type.

Referenced by exit_handler(), and main().

{
  struct msg *msg;
  struct msgctrl *msgctrl;
  msgctrl = &message_control[priority];
  pthread_mutex_lock(&msgctrl->mutex);
  if(! list_empty(&msgctrl->empty_queue)) {
    msg = list_entry(msgctrl->empty_queue.next, struct msg);
    list_del(&msg->list);
  } else {
    msg = (struct msg *)malloc(sizeof(struct msg));
  }
  msg->type = MSG_TERMINATE;
  msg->id = 0;
  msg->recurring = 0;
  msg->next_run = 0;
  list_add(&msg->list, &msgctrl->msglist);
  pthread_cond_signal(&msgctrl->cond);
  pthread_mutex_unlock(&msgctrl->mutex);
}
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines