Subversion Repositories shark

Rev

Blame | Last modification | View Log | RSS feed

/*
 *
 *
 *
 *
 */


#include "config.h"

#include <ll/i386/cons.h>

#include <kernel/func.h>
#include <kernel/int_sem.h>
#define seminit(s,v) internal_sem_init(s,v)
#define semwait(s)   internal_sem_wait(s)
#define semsignal(s) internal_sem_post(s)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>

#include <assert.h>

#include "xread.h"

/**/

/*
 */


#ifndef ACTIVATE
int x_fseek(FILE *file, long where, int from)
{
  return fseek(file,where,from);
}

size_t x_fread(void *buffer, size_t size, size_t n, FILE *file)
{
  return fread(buffer,size,n,file);
}

void x_init(void)
{}

int x_initbuffer(int group, FILE *f, int rate, int band)
{
  return XUNUSEDPID;
}

#endif

#ifdef ACTIVATE
int x_fseek(FILE *file, long where, int from)
{
  return -1;
}

#define BLOCKSIZE (512*4)
#define BLOCKSPERBUFFER (BUFFERMAXSIZE/BLOCKSIZE)

/* in millisecondi */
#define PRELOAD 500

struct xbuffer *table[OPEN_MAX];

int end_counter=0;

static TASK bufferfiller(void *arg)
{
  struct xbuffer *ptr=(struct xbuffer *)arg;
  int n;

  for (;;) {
    if (freespace(ptr)>BLOCKSIZE+8) {
      //assert(ptr->writeptr>=0);
      //assert(ptr->writeptr+BLOCKSIZE<=BUFFERMAXSIZE);
      n=read(ptr->handle,ptr->buffer+ptr->writeptr,BLOCKSIZE);
#ifdef NOGRX
      cprintf("²");
#endif
      kern_cli();
      ptr->writeptr+=n;
      /* ipotesi: non si legge mai piu' di BUFFERMAXSIZE */
      if (ptr->writeptr>=BUFFERMAXSIZE) ptr->writeptr-=BUFFERMAXSIZE;
      kern_sti();
      if (n!=BLOCKSIZE) {
        //cprintf("<XXX>");    
        break;
      }
      //assert(ptr->writeptr%512==0);      
    }
    task_endcycle();
  }
 
  end_counter++;
 
  return NULL;
}

void x_init(void)
{
  int i;
  for (i=0;i<OPEN_MAX;i++) table[i]=NULL;
}

/* rate in bits/sec */
/* band in percentuale *100 */
int x_initbuffer(int group, FILE *f, int rate, int band)
{
#ifdef EDFSCHED
  BDEDF_RES_MODEL resource;
#endif
#ifdef PSCANSCHED
  BDPSCAN_RES_MODEL resource;
#endif
  SOFT_TASK_MODEL model;
  struct xbuffer *ptr;
  int handle;
  int period,wcet;
  int n,preload;
  PID pid;
 
  handle=fileno(f);
  if (handle>OPEN_MAX||handle<0) return -11;

  if (table[handle]!=NULL) return -2;

  ptr=table[handle]=(struct xbuffer *)malloc(sizeof(struct xbuffer));
  if (ptr==NULL) return -3;

  ptr->handle=handle;
  ptr->writeptr=ptr->readptr=0;
  n=lseek(ptr->handle,0,SEEK_SET);
  if (n!=0) {
    cprintf("can't seek to 0\n");
    return -12;
  }
 
  /* PRELOAD */
  preload=rate*PRELOAD/8/1000;
  if (preload<100*1024) preload=100*1024;
  preload=(preload/BLOCKSIZE+1)*BLOCKSIZE;
  if (preload>BUFFERMAXSIZE-BLOCKSIZE) return -4;  
  n=read(ptr->handle,ptr->buffer,preload);
  if (n!=preload) {
    cprintf("preload: request %li bytes (%li returned)\n",
            (long)preload,(long)n);
    return -5;
  }
  ptr->writeptr+=n;

  //cprintf("%li bytes preloaded\n",(long)n);
  if (rate==0) sys_abort(997);
  period=1000000l*BLOCKSIZE/rate*8;
  wcet=period*band/10000;
 
  soft_task_default_model(model);    
  soft_task_def_met(model,wcet);
  soft_task_def_wcet(model,wcet);
  soft_task_def_period(model,period);  
  soft_task_def_periodic(model);
  soft_task_def_arg(model,(void*)ptr);
  soft_task_def_group(model,group);

#if defined(EDFSCHED)
  BDEDF_res_default_model(resource);
  BDEDF_res_def_dl(resource,period);
  pid=task_createn("xfill", bufferfiller,(TASK_MODEL*)&model, &resource, NULL);
#elif defined(PSCANSCHED)
  BDPSCAN_res_default_model(resource);
  BDPSCAN_res_def_priority(resource,0);
  pid=task_createn("xfill", bufferfiller,(TASK_MODEL*)&model, &resource, NULL);
#else
  pid=task_create("xfill", bufferfiller, &model, NULL);
#endif
  if (pid!=-1) {
    cprintf("task wcet=%10li period=%10li\n",(long)wcet,(long)period);
  }
 
  return pid;
}

size_t x_fread(void *buffer, size_t objsize, size_t n, FILE *file)
{
  struct xbuffer *ptr;
  int size,sz;
  int nv;
 
  ptr=table[fileno(file)];
  if (ptr==NULL) {
    cprintf("x_fread with bad fd\n");
    return 0;
  }
 
  size=objsize*n;
  //cprintf("[for %i]",size);
REDO:
  if (filledspace(ptr)<size) {
    /*
    cprintf("x_fread called for %li bytes (%li available)\n",
            (long)size,
            (long)filledspace(ptr));
    */

    nv=n;
    n=filledspace(ptr)/objsize;
    if (n==0) {
      struct timespec delay;
      delay.tv_sec=0;
      delay.tv_nsec=15000000;
      n=nv;
      nanosleep(&delay, 0);
      goto REDO;
      return 0;
    }
    size=objsize*n;
    /*cprintf("%i will return\n",size);*/
  }
     
  sz=BUFFERMAXSIZE-ptr->readptr;
  if (sz>=size) {
    //cprintf("X");
    memcpy(buffer,ptr->buffer+ptr->readptr,size);
  } else {
    //cprintf("Y");
    memcpy(buffer,ptr->buffer+ptr->readptr,sz);
    assert(size-sz>0);
    memcpy(buffer+sz,ptr->buffer,size-sz);
  }

  kern_cli();
  ptr->readptr+=size;
  /* ipotesi: non si legge mai piu' di BUFFERMAXSIZE */
  if (ptr->readptr>=BUFFERMAXSIZE) ptr->readptr-=BUFFERMAXSIZE;
  kern_sti();
 
  return n;
}

#endif