SASC
DVBSoftCAM

msg_passing.c File Reference

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <pthread.h>
#include <string.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sched.h>
#include <linux/dvb/frontend.h>
#include <linux/dvb/dmx.h>
#include "process_req.h"
#include "plugin_getsid.h"
#include "plugin_ringbuf.h"
#include "msg_passing.h"

Go to the source code of this file.

Classes

struct  msgctrl

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 *))
static struct msg * msg_add_type_to_list (unsigned int priority, int type, int id, int replace)
void msg_send_replace (unsigned int priority, int type, int id, void *data, int delay, unsigned int flags)
void msg_terminate (unsigned int priority)

Variables

static struct msgctrl message_control [MSG_HIGH_PRIORITY+1]

Function Documentation

static struct msg* msg_add_type_to_list ( unsigned int  priority,
int  type,
int  id,
int  replace 
) [static, read]

Definition at line 156 of file msg_passing.c.

References msgctrl::empty_queue, id, msg::id, msg::list, list_add_tail(), list_del(), list_empty(), list_entry, list_for_each, message_control, msgctrl::msglist, list_head::next, msg::next_run, msg::recurring, and msg::type.

Referenced by msg_send_replace().

                                                     {
  struct list_head *ptr;
  struct msg *msg;
  struct msgctrl *msgctrl;

  msgctrl = &message_control[priority];

  if(replace) {
    //if a message of this type is already on the list
    list_for_each(ptr, &msgctrl->msglist) {
      msg = list_entry(ptr, struct msg);
      if (msg->type == type && msg->id == id) {
        return msg;
      }
    }
  }
  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));
  }
  list_add_tail(&msg->list, &msgctrl->msglist);
  msg->type = type;
  msg->id = id;
  msg->recurring = 0;
  msg->next_run = 0;
  return msg;
}
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 *)  cmd 
)

Definition at line 134 of file msg_passing.c.

References cmd, msg::data, msgctrl::empty_queue, msg::id, msg::list, list_add(), list_del(), list_entry, list_for_each, message_control, MSG_HIGH_PRIORITY, msgctrl::msglist, msgctrl::mutex, and msg::type.

Referenced by fe_close(), fe_tune(), and process_ffd().

                                                    {
  struct list_head *ptr;
  struct msgctrl *msgctrl;

  if (priority > MSG_HIGH_PRIORITY)
    return;
  msgctrl = &message_control[priority];
  pthread_mutex_lock(&msgctrl->mutex);
  list_for_each(ptr, &msgctrl->msglist) {
    struct msg *msg = list_entry(ptr, struct msg);
    if (msg->type == type && msg->id == id) {
      list_del(&msg->list);
      if(cmd)
        cmd(msg->data);
      list_add(&msg->list, &msgctrl->empty_queue);
      break;
    }
  }
  pthread_mutex_unlock(&msgctrl->mutex);
}
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);
}

Variable Documentation

struct msgctrl message_control[MSG_HIGH_PRIORITY+1] [static]
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines