Solved

linking objects

Posted on 2004-03-22
6
328 Views
Last Modified: 2010-05-18
i try to link link object that i get after i assemble the assembly source code idon`t know how can i link the obeject with the other object file of my c++ program  
0
Comment
Question by:akayed
  • 3
  • 3
6 Comments
 
LVL 1

Expert Comment

by:while_true
ID: 10648488
On what platform do you want to link ? using which compiler ?
0
 

Author Comment

by:akayed
ID: 10662456
iam using turbo c++ compiler on windows xp professional there ihave two files one is the object from the source code and other is the object from assembly source code when try to run it gives me error i think it's linking error because when i compile my  file (tempo.cpp) no errors will appear .
 
0
 
LVL 1

Expert Comment

by:while_true
ID: 10665184
I'm afraid, that your problem is a problem depending on the c++ name mangling of the c++ compiler (decorated function names): To allow function overloading ( func( int ), func( char *), ...) c++ compilers are 'mangling' the types of function parameters into the function name. Every compiler has its own algorithm to do this. Therefore it is sometimes impossible to link object files/libraries compiled with different compilers.

Which assembler are you using ? Are you calling c++ methods from assembler code ? When you use the MS Macro Assembler, the above described circumstances can cause the the problem when you try to link to borland compiled object files.
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:akayed
ID: 10673562
program called tempo kernel i want to compile this code by c++ compiler in turbo c++

note: all these source codes are in the following site
ftp://ftp.sce.carleton.ca/pub/RealTimeBook/tempo/

// ch2ex1.cpp - a process that prints "Hello, world!"

#include <iostream.h>
#include "tempo.h"

// The root function for the Main process
void Main()
{
    CS(cout << "Hello, world!" << endl);
}
i have all header file that thats the source code need .
i have another code called tempo.cpp  this file contain this code


//
//  tempo.cpp

#include        <iostream.h>
#include        <stdlib.h>
#include           <dos.h>            //setvect() and getvect()
#include        "tempo.h"

const float release = 0.98;


// This points to the single Scheduler object that is created
// by Scheduler::Instance()
Scheduler *Scheduler::InstancePtr = 0;

//----------------------------------------------------------------
// Queue management

inline int QueueLink::empty()
{
      return (next == this);
}

void QueueLink::enqueue(QueueLink *link)
{
      link->prev = prev;
      link->next = this;
      prev->next = link;
      prev = link;
}

QueueLink *QueueLink::dequeue()
{
      QueueLink   *link;

      if (empty())  {
            return (NULL);
      }
      link = next;
      next = link->next;
      link->next->prev = link->prev;
      link->next = link;
    link->prev = link;
      return (link);
}

void QueueLink::remove()
{
      prev->next = next;
      next->prev = prev;
      next = this;
    prev = this;
}

//--------------------------------------------------------------------
// Delta queue management
//

struct DeltaQueueElement {
      PD *Element;
      DeltaQueueElement *Next;
      unsigned int Delta;
};

struct Queue {
      DeltaQueueElement *Head;
};

Queue sleepq;

#define TIMER 8
void interrupt (*oldhandler)(...);
void interrupt timerISR(...);

void InitDeltaQueue(Queue& q)
{
      q.Head = NULL;
}

void DeltaEnqueue(Queue& q, PD *Element, unsigned int Delta)
// Queues up the passed element on the queue.
{
      DeltaQueueElement *NewDeltaElementAt;
      DeltaQueueElement *CurrentDeltaElementAt;
      DeltaQueueElement *OldDeltaElementAt;

      NewDeltaElementAt = new DeltaQueueElement;
      NewDeltaElementAt->Element = Element;
      NewDeltaElementAt->Next = NULL;
      NewDeltaElementAt->Delta = Delta;

      if (q.Head == NULL) {
            // Add element to an empty delta queue
            q.Head = NewDeltaElementAt;
      } else {
            CurrentDeltaElementAt = q.Head;
            OldDeltaElementAt = NULL;

            while ((CurrentDeltaElementAt != NULL) &&
                     (CurrentDeltaElementAt->Delta < NewDeltaElementAt->Delta)) {
                     NewDeltaElementAt->Delta = NewDeltaElementAt->Delta - CurrentDeltaElementAt->Delta;
                     OldDeltaElementAt = CurrentDeltaElementAt;
                     CurrentDeltaElementAt = CurrentDeltaElementAt->Next;
            }
            if (OldDeltaElementAt == NULL) {
                  if (CurrentDeltaElementAt->Delta < NewDeltaElementAt->Delta) {
                        NewDeltaElementAt->Delta = NewDeltaElementAt->Delta - CurrentDeltaElementAt->Delta;
                        NewDeltaElementAt->Next = CurrentDeltaElementAt->Next;
                        CurrentDeltaElementAt->Next = NewDeltaElementAt;
                  } else {
                        CurrentDeltaElementAt->Delta = CurrentDeltaElementAt->Delta - NewDeltaElementAt->Delta;
                        q.Head = NewDeltaElementAt;
                        NewDeltaElementAt->Next = CurrentDeltaElementAt;
                  }
            } else if (CurrentDeltaElementAt == NULL) {
                  OldDeltaElementAt->Next = NewDeltaElementAt;
            } else {
                  CurrentDeltaElementAt->Delta = CurrentDeltaElementAt->Delta - NewDeltaElementAt->Delta;
                  OldDeltaElementAt->Next = NewDeltaElementAt;
                  NewDeltaElementAt->Next = CurrentDeltaElementAt;
            }
      }
}

PD *DeltaDequeue(Queue& q)
// If the delta of the first element of the queue is 0,
// the first element is dequeued and returned;
// otherwise NULL is returned.
{
      DeltaQueueElement *CurrentDeltaElementAt;
      PD *Element;

      Element = NULL;
      CurrentDeltaElementAt = q.Head;
      if (CurrentDeltaElementAt != NULL) {
            if (CurrentDeltaElementAt->Delta == 0) {
                  q.Head = CurrentDeltaElementAt->Next;
                  Element = CurrentDeltaElementAt->Element;
                  delete CurrentDeltaElementAt;
             }
      }
      return Element;
}

void deltaDecrement(Queue& q)
// Decrements the counter of the first element of a delta queue.
{
      DeltaQueueElement *CurrentDeltaElementAt;

      CurrentDeltaElementAt = q.Head;
      if (CurrentDeltaElementAt != NULL) {
            --CurrentDeltaElementAt->Delta;
      }
}

unsigned int DeltaRemoveElement(Queue& q, PD *Element)
{
      unsigned int SearchDone;
      unsigned int Status;
      DeltaQueueElement *PreviousDeltaElementAt;
      DeltaQueueElement *NextDeltaElementAt;
      DeltaQueueElement *CurrentDeltaElementAt;

      Status = 1; // 1 indicates element not found

      CurrentDeltaElementAt = q.Head;
      PreviousDeltaElementAt = NULL;
      SearchDone = (CurrentDeltaElementAt == NULL);
      while (!SearchDone) {
            if (CurrentDeltaElementAt->Element == Element) {
                  Status = 0;  // Element has been found
                  SearchDone = 1;
                  if (PreviousDeltaElementAt == NULL) {
                        q.Head = CurrentDeltaElementAt->Next;
                  } else {
                        PreviousDeltaElementAt->Next = CurrentDeltaElementAt->Next;
                  }
                  NextDeltaElementAt = CurrentDeltaElementAt->Next;
                  if (NextDeltaElementAt != NULL) {
                        NextDeltaElementAt->Delta = NextDeltaElementAt->Delta + CurrentDeltaElementAt->Delta;
                  }
                  delete CurrentDeltaElementAt;
            } else {
                  PreviousDeltaElementAt = CurrentDeltaElementAt;
                  CurrentDeltaElementAt = CurrentDeltaElementAt->Next;
                  SearchDone = (CurrentDeltaElementAt == NULL);
            }
      }
      return Status;
}

//-------------------------------------------------------------
// Scheduler
//
Scheduler::Scheduler()
{
      cout << "Tempo release " << release << endl;
    cout << "Initializing scheduler" << endl;

    InstancePtr = this;
      numprocesses = 0;

      // initialize the sleep queue
      InitDeltaQueue(sleepq);

      CurStackBase = InitStackBase();
      CurStackBase = CurStackBase - INIT_STACK;

      cout << "Creating the idle process" << endl;
      idleProcess = new PD(NULL, IDLE_PRIORITY, IDLE_STACK);
}

//  allocStackSpace() - allocate stack space for a process.
//
char *Scheduler::allocStackSpace(unsigned size)
{
      char *base;

      if (size < MIN_STACK) {
            size = MIN_STACK;
      }
      base = CurStackBase;
      CurStackBase = CurStackBase - size;
      return base;
}

//  addready() - add process p to the list of ready-to-run processes.
//
inline void Scheduler::addready(PD *p)
{
      // add 1 to process priority, because ReadyList[0] is
      // the ready queue for processes with priority -1
      readyList[(p->priority)+1].enqueue(&p->Queue);
}

//  removeready() - remove process p from the list of ready-to-run processes.
//
inline void Scheduler::removeready(PD *p)
{
      p->Queue.remove();
}

// addNewProcess() - called when a new process is created
// to increment the scheduler's count of processes and
// to make the process ready to run.
//
char Scheduler::addNewProcess(PD *p)
{
      numprocesses++;
      p->makeProcessReady();
      addready(p);
      return(TRUE);
}

// removeprocess() - reduce the count of active processes by one
//
void Scheduler::removeprocess()
{
      numprocesses--;
      if (numprocesses == 1) {      // only the null process is left
            terminate_multitasking();
      }
      resched();
}

//  Scheduler::resched()
//  Selects the next ready-to-run process from the RTR list,
//  then performs a context switch to that process.
//
void Scheduler::resched()
{
      PD              *oldProcess;
      PD              *newProcess;
      int             priority;

      for (priority = HIGHEST_PRIORITY;
           priority >= IDLE_PRIORITY;
           --priority) {
            if (!readyList[priority+1].empty()) {
                  newProcess = (PD *)readyList[priority+1].dequeue();
                  break;
            }
      }

      // If calling process is still ready and is the highest
      // priority ready process, just return
      if (newProcess == activeProcess) {
            activeProcess->makeProcessActive();
            return;
      }

      oldProcess = activeProcess;
      activeProcess = newProcess;
      activeProcess->makeProcessActive();
      switchContext(&oldProcess->registers, &activeProcess->registers);
}

//  Scheduler::reliquish()
//  Called by processes when they are ready to give up the
//  processor.  If there are any other ready processes with
//  equal or higher priority than the caller's priority,
//  rescheduling occurs.
//
void Scheduler::relinquish()
{
      short       savedFlags;

      savedFlags = disable_ints();
      activeProcess->makeProcessReady();
      addready(activeProcess);
      resched();
      restore_flags(savedFlags);
}


void Scheduler::startMultiTasking()
{

    // initialize the isr that wakes up sleeping processes
    cout << "Installing timer ISR" << endl;
      oldhandler = getvect(TIMER);
      setvect(TIMER, timerISR);

    cout << "Starting multitasking" << endl;
      removeready(idleProcess);
      activeProcess = idleProcess;
      idleProcess->makeProcessActive();
      relinquish();

      while(TRUE);
}

// Instance() creates an instance of the scheduler,
// but only if no other instances have been created.
// N.B. Calling this function is the only way to
// create a Scheduler object. The constructor for
// class Scheduler is private, so it is not possible to
// instantiate Scheduler objects from outside the class.
// This is based on the singleton pattern in the
// Gang-of-Four book.
void Scheduler::Instance()
{
    if (InstancePtr == 0) {
       InstancePtr = new Scheduler();
    }
}

// Constructor for class PD
//
PD::PD(void (*rootFnPtr)(),
       int Processpriority,
       unsigned stackSize)
       : Queue()
{
      short       *stackPointer;

      // Initialize the stack so that the root function
      // for this process returns to processDone().
      stackPointer = (short*)Scheduler::InstancePtr->allocStackSpace(stackSize);
      *stackPointer =(short)PD::processDone;


      InitPregs(&this->registers, (short)stackPointer, (short)rootFnPtr);

      priority = Processpriority;

      // Init the process' event queues
      for (int i = 0; i < MAX_QUEUES; ++i) {
            eventQueue[i].count= 0;
            eventQueue[i].mask = UNMASKED;
      }
      signaledOn = -1;

      // Ask the scheduler to add this process to its
      // list of ready-to-run processes.
      Scheduler::InstancePtr->addNewProcess(this);
}

//  processDone()
//  When the root function for a process returns, it executes
//  this function.
//
void PD::processDone()
{
      Scheduler::InstancePtr->removeprocess();
}


// create_process() - create a new Tempo process
Process create_process(void (*rootFnPtr)(), int priority)
{
    Process p;
    short savedFlags;

    savedFlags = disable_ints();
    p = new PD(rootFnPtr, priority);
    restore_flags(savedFlags);
    return p;
}

// process_sleep() - the calling process is put
// to sleep for "time" ticks of the system timer
void PD::process_sleep(unsigned int time)
{
      short savedFlags;

      savedFlags = disable_ints();

      if (time > 0) {
            makeProcessSleepBlocked();
            DeltaEnqueue(sleepq, this, time);
            Scheduler::InstancePtr->resched();
      }
      restore_flags(savedFlags);
}

void interrupt timerISR(...)
{
      PD *wakeUp;
      short savedFlags;
      int contextSwitchNeeded;

      // daisy chain to the old timer ISR
      oldhandler();

      // When we return from the old ISR, interrupts
      // have been enabled and EOI has been sent to the
      // PIC. Now check for waiting processes that have
      // timed out and sleeping processes that must be
      // awakened.
      savedFlags = disable_ints();
      contextSwitchNeeded = FALSE;
      PD *active = Scheduler::InstancePtr->activeProcess;
      deltaDecrement(sleepq);
      wakeUp = DeltaDequeue(sleepq);
      while (wakeUp != NULL) {
            if (wakeUp->myState() == SEM_TIMED_BLOCKED) {
                  // A process that is blocked on a
                  // semaphore has timed out. Remove it
                  // from the semaphore queue.
                  wakeUp->Queue.remove();
            }
            wakeUp->timedOut = TRUE;
            wakeUp->makeProcessReady();
            Scheduler::InstancePtr->addready(wakeUp);
            if (wakeUp->priority > active->priority)
                  contextSwitchNeeded = TRUE;

            wakeUp = DeltaDequeue(sleepq);
      }
      if (contextSwitchNeeded) {
            active->makeProcessReady();
            Scheduler::InstancePtr->addready(active);
            Scheduler::InstancePtr->resched();
      }
      restore_flags(savedFlags);
}

// wait() - wait on this process' event queues until one of them is signaled
int PD::wait()
{
      short savedFlags;
      int   i;
      int signaled;

      savedFlags = disable_ints();

      for (i = 0; i < MAX_QUEUES; i++) {
            if ((eventQueue[i].mask == UNMASKED) &&
                  (eventQueue[i].count > 0)) {    // no need to block waiter
                        eventQueue[i].count--;
                        restore_flags(savedFlags);
                        return i;
            }
      }
      makeProcessQueueBlocked();
      Scheduler::InstancePtr->resched();
      signaled = signaledOn;
      signaledOn = -1;
      restore_flags(savedFlags);
      return signaled;
}

int PD::wait(unsigned int timeout)
{
      short savedFlags;
      int   i;
      int signaled;
    int status;

      savedFlags = disable_ints();
    timedOut = FALSE;
      for (i = 0; i < MAX_QUEUES; i++) {
            if ((eventQueue[i].mask == UNMASKED) &&
                  (eventQueue[i].count > 0)) {    // no need to block waiter
                        eventQueue[i].count--;
                        restore_flags(savedFlags);
                        return i;
            }
      }
    if (timeout == 0) {
      signaled = TIMED_OUT;
    } else {   // timeout > 0
      DeltaEnqueue(sleepq, Scheduler::InstancePtr->activeProcess, timeout);
      makeProcessQueueTimedBlocked();
      Scheduler::InstancePtr->resched();
      if (timedOut)
          signaled = TIMED_OUT;
      else
          signaled = signaledOn;
    }
      signaledOn = -1;
      restore_flags(savedFlags);
      return signaled;
}

void PD::signal(int queue_number)
{
      short savedFlags;
      PD *active;    // pointer to the currently running process

      if ((queue_number < 0) || (queue_number >= MAX_QUEUES))
            return;

      savedFlags = disable_ints();

      if (((state == QUEUE_BLOCKED) || (state == QUEUE_TIMED_BLOCKED)) &&
            (eventQueue[queue_number].mask == UNMASKED)) {
      if (state == QUEUE_TIMED_BLOCKED)
          DeltaRemoveElement(sleepq, this);
            makeProcessReady();
            signaledOn = queue_number;
            Scheduler::InstancePtr->addready(this);
            if (priority >
                Scheduler::InstancePtr->activeProcess->priority) {
                Scheduler::InstancePtr->activeProcess->makeProcessReady();
                  Scheduler::InstancePtr->addready(
                           Scheduler::InstancePtr->activeProcess);
                Scheduler::InstancePtr->resched();
             }
      } else {
            eventQueue[queue_number].count++;
      }
      restore_flags(savedFlags);
}

void PD::send(int queue, message msg, int ack_queue)
{
      short savedFlags;
      PD *active;    // pointer to the currently running process

      if ((queue < 0) || (queue >= MAX_QUEUES))
            return;

      savedFlags = disable_ints();

      MsgNode *node = new MsgNode;
      node->msg = msg;
      node->ack_queue = ack_queue;
      node->correspondent = Scheduler::InstancePtr->activeProcess;
      eventQueue[queue].enqueue(&node->Queue);

      if (((state == QUEUE_BLOCKED) || (state == QUEUE_TIMED_BLOCKED)) &&
          (eventQueue[queue].mask == UNMASKED)) {
      if (state == QUEUE_TIMED_BLOCKED)
          DeltaRemoveElement(sleepq, this);
            makeProcessReady();
            Scheduler::InstancePtr->addready(this);
            if (priority >
                Scheduler::InstancePtr->activeProcess->priority) {
                Scheduler::InstancePtr->activeProcess->makeProcessReady();
                Scheduler::InstancePtr->addready(
                           Scheduler::InstancePtr->activeProcess);
                Scheduler::InstancePtr->resched();
             }
      }
      restore_flags(savedFlags);
}

int PD::receive(message &msg, Process &correspondent, int &ack_queue)
{
      short savedFlags;
      int   i;
      MsgNode *node;
      int signaled;

      savedFlags = disable_ints();

      for (i = 0; i < MAX_QUEUES; i++) {
            if ((eventQueue[i].mask == UNMASKED) &&
                  (eventQueue[i].count > 0)) {    // no need to block waiter
                        eventQueue[i].count--;
                        msg = NULL;
                        correspondent = NULL;
                        ack_queue = NULL;
                        restore_flags(savedFlags);
                        return i;
            }
      }
search_again:
      for (i = 0; i < MAX_QUEUES; i++) {
            if ((eventQueue[i].mask == UNMASKED) &&
                  (!eventQueue[i].empty())) {
                        node = (MsgNode *)eventQueue[i].dequeue();
                        msg = node->msg;
                        correspondent = node->correspondent;
                        ack_queue = node->ack_queue;
                        delete node;
                        restore_flags(savedFlags);
                        return i;
            }
      }
      makeProcessQueueBlocked();
      Scheduler::InstancePtr->resched();
      if (signaledOn != -1) {
            signaled = signaledOn;
            signaledOn = -1;
            msg = NULL;
            correspondent = NULL;
            ack_queue = NULL;
            restore_flags(savedFlags);
            return signaled;
      } else {
            goto search_again;
      }
}

int PD::receive(message &msg, Process &correspondent, int &ack_queue, unsigned int timeout)
{
      short savedFlags;
      int   i;
      MsgNode *node;
      int signaled;

      savedFlags = disable_ints();
    timedOut = FALSE;
      for (i = 0; i < MAX_QUEUES; i++) {
            if ((eventQueue[i].mask == UNMASKED) &&
                  (eventQueue[i].count > 0)) {    // no need to block waiter
                        eventQueue[i].count--;
                        msg = NULL;
                        correspondent = NULL;
                        ack_queue = NULL;
                        restore_flags(savedFlags);
                        return i;
            }
      }
search_again:
      for (i = 0; i < MAX_QUEUES; i++) {
            if ((eventQueue[i].mask == UNMASKED) &&
                  (!eventQueue[i].empty())) {
                        node = (MsgNode *)eventQueue[i].dequeue();
                        msg = node->msg;
                        correspondent = node->correspondent;
                        ack_queue = node->ack_queue;
                        delete node;
                        restore_flags(savedFlags);
                        return i;
            }
      }
    if (timeout == 0) {
      msg = NULL;
      correspondent = NULL;
      ack_queue = NULL;
      restore_flags(savedFlags);
      return TIMED_OUT;
    } else { // timeout > 0
      DeltaEnqueue(sleepq, Scheduler::InstancePtr->activeProcess, timeout);
      makeProcessQueueTimedBlocked();
      Scheduler::InstancePtr->resched();
      if (timedOut) {
          msg = NULL;
          correspondent = NULL;
          ack_queue = NULL;
          restore_flags(savedFlags);
          return TIMED_OUT;
      }
          if (signaledOn != -1) {
            signaled = signaledOn;
            signaledOn = -1;
                msg = NULL;
            correspondent = NULL;
            ack_queue = NULL;
            restore_flags(savedFlags);
            return signaled;
          } else {
                goto search_again;
      }
    }
}

void PD::maskqueue(int queue_number)
{
      if ((queue_number >= 0) && (queue_number < MAX_QUEUES))
            eventQueue[queue_number].mask = MASKED;
}

void PD::unmaskqueue(int queue_number)
{
      if ((queue_number >= 0) && (queue_number < MAX_QUEUES))
            eventQueue[queue_number].mask = UNMASKED;
}


//  Sem::Sem
//  Constructor for objects of the class Sem
//
Sem::Sem(int initialCount)
{
      count = initialCount;
}

// Called by a process to wait on a semaphore without a timeout
void Sem::wait()
{
      short       savedFlags;

      savedFlags = disable_ints();
      if (count > 0) {
            --count;
      } else {
            // block the caller
            PD* active = Scheduler::InstancePtr->activeProcess;
            active->makeProcessBlocked();
            // move the active process to the
            // semaphore queue
            enqueue(&active->Queue);
            Scheduler::InstancePtr->resched();
      }
      restore_flags(savedFlags);
}

// Called by a process to wait on a semaphore with a timeout
int Sem::wait(unsigned int timeout)
{
      short   savedFlags;
      int      status;

      savedFlags = disable_ints();
      Scheduler::InstancePtr->activeProcess->timedOut = FALSE;
      status = 0;
      if (count) {
            --count;
      } else  if (timeout == 0) {
            status = TIMED_OUT;
      } else {
        PD* active = Scheduler::InstancePtr->activeProcess;
        // time > 0, so block the caller
            // add a pointer to the calling process to the sleep queue
            DeltaEnqueue(sleepq, active, timeout);
            // block the calling process on the semaphore queue
            active->makeProcessSemaphoreTimedBlocked();
            enqueue(&active->Queue);
            Scheduler::InstancePtr->resched();
            if (active->timedOut)
                  status = TIMED_OUT;
      }
      restore_flags(savedFlags);
      return status;
}

//  Signal a semaphore
void Sem::signal()
{
      short savedFlags;
      PD    *p;

      savedFlags = disable_ints();
      if (empty())
      {
            // No processes are blocked on the semaphore
            ++count;
      } else {
            // Get the process at the front of the
            // semaphore queue.
            p  = (PD*)dequeue();

            // If the process specified a timeout
            // when it called wait_semaphore(),
            // remove the process from the sleep queue.
            if (p->myState() == SEM_TIMED_BLOCKED)
                  (void)DeltaRemoveElement(sleepq, p);
            p->makeProcessReady();
            Scheduler::InstancePtr->addready(p);
            if (p->priority >
                  Scheduler::InstancePtr->activeProcess->priority) {
                        Scheduler::InstancePtr->activeProcess->makeProcessReady();
                        Scheduler::InstancePtr->addready(
                              Scheduler::InstancePtr->activeProcess);
                        Scheduler::InstancePtr->resched();
            }
      }
      restore_flags(savedFlags);
}


Semaphore create_semaphore(int initial_count)
{
      Semaphore s;
      short savedFlags;

      savedFlags = disable_ints();
      s = new Sem(initial_count);
      restore_flags(savedFlags);
      return s;
}


Semaphore Tempo_mutex;   // used by the CS macro

// There's not much to this function, because most of the kernel's
// initialization takes place when the scheduler's constructor runs.
void initialize_Tempo()
{
    // create one instance of the scheduler
    Scheduler::Instance();
      Tempo_mutex = create_semaphore(1);
}

void become_idle()
{
      Scheduler::InstancePtr->startMultiTasking();
}

void terminate_multitasking()
{
            cout << "All user processes finished, exiting Tempo" << endl;
            setvect(TIMER, oldhandler);
            exit(0);
}

extern void Main();

Process MainProcess;

//  main()
//
void main()
{
      // initialize kernel data structures
      initialize_Tempo();
      // create the first process from user's Main()
    cout << "Creating Main process" << endl;
      MainProcess = create_process(Main, 0);
      // become the idle process and
      // start the Main process executing
      become_idle();   // this call never returns
}

and i have tempo.h in include file and file called kernel.h .
there are assembly file that i assemble it and i have object from it called machine.obj ,and the source code for this machine.asm
all these file are in this site ftp://ftp.sce.carleton.ca/pub/RealTimeBook/tempo/
i read the readme file i do every thing except the linking because try to do it but ihave erorrs in file tempo.cpp when i try to link the object that i have after i run  the tempo.cpp the errors after running  it i have linking error all files are in bin directory in tc c++
and the header file are in te include directory in tc
 
 
 
0
 
LVL 1

Accepted Solution

by:
while_true earned 50 total points
ID: 10675272
akayed,
you don't need to post the complete code here. After reading what you said I assume, that you are assembling and compiling both with Borland Turbo C++.
Can you post the linker error messages ? Possibly they will lead us to the solution (normally they should ! ;-) ).
0
 

Author Comment

by:akayed
ID: 10682802
when i have all object i try to run  of the ch2ex1 file (this file contain the

main file)  the linking box give it has lines compiled and link pass 2
and 4 errors these errors are :

linker error:undefined symbol _MAIN in module c0.asm
linker error:undefined symbol _TEMPO_MUTEX in module ch2ex1.cpp
linker error:undefined symbol _sem::wait() in module ch2ex1.cpp
linker error:undefined symbol _sem::signal() in module ch2ex1.cpp
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now