Subversion Repositories shark

Rev

Blame | Last modification | View Log | RSS feed

/* Project:     OSLib
 * Description: The OS Construction Kit
 * Date:                1.6.2000
 * Idea by:             Luca Abeni & Gerardo Lamastra
 *
 * OSLib is an SO project aimed at developing a common, easy-to-use
 * low-level infrastructure for developing OS kernels and Embedded
 * Applications; it partially derives from the HARTIK project but it
 * currently is independently developed.
 *
 * OSLib is distributed under GPL License, and some of its code has
 * been derived from the Linux kernel source; also some important
 * ideas come from studying the DJGPP go32 extender.
 *
 * We acknowledge the Linux Community, Free Software Foundation,
 * D.J. Delorie and all the other developers who believe in the
 * freedom of software and ideas.
 *
 * For legalese, check out the included GPL license.
 */


/*      Address Spaces test file                        */

#include <ll/i386/stdlib.h>
#include <ll/i386/error.h>
#include <ll/i386/mem.h>
#include <ll/i386/hw-arch.h>
#include <ll/i386/farptr.h>
#include <ll/sys/ll/ll-func.h>
#include <ll/sys/ll/aspace.h>
#include <ll/sys/ll/event.h>

#define T  1000
#define WAIT()  for (w = 0; w < 0x5FFFFF; w++)                                

extern DWORD GDT_base;

BYTE space[2048];
BYTE stack1[1024];
WORD th1, th2, thm;

/* For now, this is not called */
void killer(void)
{
  cli();
  message("Killer!!!\n");
  ll_context_load(thm);
}

/* Used to switch back to main thread */
void evtHandler(void *v)
{
  ll_context_load(thm);
}

/*
   Dummy thread: used only to test a context switch between two threads
   in the same AS
*/

void nullfun1(void *p)
{
  message("In thread 1\n");
  ll_context_load(thm);
}

/*
  And this is the thread that runs in the new AS... It cannot call
  any function (it is alone in its AS), so it simply plots a star
  on the screen and loops waiting for an event that switches to the
  main thread.
*/

void nullfun(void *p)
{
  /* Some asm to write on the screen (we cannot use libc... it is not
     linked in this AS */

  __asm__ __volatile__ ("movl $0xb8000, %ebp");
  __asm__ __volatile__ ("addl $150, %ebp");
  __asm__ __volatile__ ("movb $'*', %fs:0(%ebp)");
  __asm__ __volatile__ ("incl %ebp");
  __asm__ __volatile__ ("movb $6, %fs:0(%ebp)");

  /* And now, WAIT!!! */
  for(;;);
  halt();
}

int main (int argc, char *argv[])
{
  DWORD sp1, sp2;
  void *res;
  AS as, ds;
  int ok;
  char mystring[20];
  struct ll_initparms parms;
  struct timespec time;
 
  sp1 = get_SP();
  cli();
  if ((argc == 2) && (argv[1][0] == 'O')) {
    parms.mode = LL_ONESHOT;
  } else {
    parms.mode = LL_PERIODIC;
    parms.tick = 1000;
  }
  res = ll_init();
  event_init(&parms);

  if (res == NULL) {
    message("Error in LowLevel initialization code...\n");
    sti();
    l1_exit(-1);
  }
  NULL_TIMESPEC(&time);
  ADDNANO2TIMESPEC(500000000, &time);
  ADDNANO2TIMESPEC(500000000, &time);
  ADDNANO2TIMESPEC(500000000, &time);
  ADDNANO2TIMESPEC(500000000, &time);
  ADDNANO2TIMESPEC(500000000, &time);
  ADDNANO2TIMESPEC(500000000, &time);
  ADDNANO2TIMESPEC(500000000, &time);
  ADDNANO2TIMESPEC(500000000, &time);
  ADDNANO2TIMESPEC(500000000, &time);
  ADDNANO2TIMESPEC(500000000, &time);        /* Time1: 5 ms */
  event_post(time, evtHandler, NULL);
  sti();

  message("LowLevel started...\n");
   
  as_init();

  message("Creating an Address Space\n");
  as = as_create();
  message("Created: ID = %d %x\n", as, as);
  message("Binding array @ 0x%lx\n", (DWORD)space);
  ok = as_bind(as, (DWORD)space, 0, sizeof(space));

  if (ok < 0) {
    message("Error in as_bind!!!\n");
  } else {
    message("Bound\n");
  }
  _farpokeb(as, 0, 'H');
  _farpokeb(as, 1, 'e');
  _farpokeb(as, 2, 'l');
  _farpokeb(as, 3, 'l');
  _farpokeb(as, 4, 'o');
  _farpokeb(as, 5, 0);

  ds = get_DS();
  fmemcpy(ds, (DWORD)mystring, as, 0, 10);
  message("Memory space: %s\n", space);
  message("My String: %s\n", mystring);

  fmemcpy(as, 0, ds, (DWORD)nullfun, 1000);
  /* Create a thread (in our AS) and a task (in a different AS) */
  th2 = ll_context_create(nullfun1, &stack1[1024], NULL,killer, 0);
  th1 = ll_context_create(0, (void *)2048, NULL,killer, 0);
  ll_context_setspace(th1, as);
       
  /* Save our context, in order to permit to switch back to main */
  thm = ll_context_save();
  message("I am thread %x\n", thm);
  message("Thread 1 created\n");
  message("Switching to it...\n");
  ll_context_load(th2);
  message("Back to Main\n");

  /* Plot something in a stupid way, just to do some work... */
  __asm__ __volatile__ ("movl $0x30, %eax");
  __asm__ __volatile__ ("movw %ax, %fs");
  __asm__ __volatile__ ("movl $0xb8000, %edi");
  __asm__ __volatile__ ("addl $152, %edi");
  __asm__ __volatile__ ("movb $'+', %ds:0(%edi)");
  __asm__ __volatile__ ("incl %edi");
  __asm__ __volatile__ ("movb $6, %ds:0(%edi)");
 
  /* And now, go to the new task!!! */
  ll_context_load(th1);

  message("Main task again...\n");

  __asm__ __volatile__ ("movl $0x30, %eax");
  __asm__ __volatile__ ("movw %ax, %fs");
  __asm__ __volatile__ ("movl $0xb8000, %edi");
  __asm__ __volatile__ ("addl $154, %edi");
  __asm__ __volatile__ ("movb $'-', %fs:0(%edi)");
  __asm__ __volatile__ ("incl %edi");
  __asm__ __volatile__ ("movb $6, %fs:0(%edi)");

  message("Current time: %ld (= %ld?)\n", ll_gettime(TIME_NEW, NULL),
          ll_gettime(TIME_EXACT, NULL));
  cli();
  ll_end();
  sp2 = get_SP();
  message("End reached!\n");
  message("Actual stack : %lx - ", sp2);
  message("Begin stack : %lx\n", sp1);
  message("Check if same : %s\n",sp1 == sp2 ? "Ok :-)" : "No :-(");
 
  return 1;
}