2013-03-05 1 views
1

У меня есть две программы, которые я создал. Один из них - myThreads.c, а другой - myThreads_test.c, все в одном каталоге. Внутри этого каталога у меня также есть libslack.c, который я использую для его возможностей списка. Финлей, у меня есть myThreads.hМногие недопустимые индексы символов и неопределенные ссылки на основные

Я пытаюсь скомпилировать с помощью:

gcc -o myThreads_test.c myThreads.c -DHAVE_PTHREAD_RWLOCK=1 -lslack -lrt 

или

gcc -o myThreads.c myThreads_test.c -DHAVE_PTHREAD_RWLOCK=1 -lslack -lrt 

и получить следующие ошибки:

/usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 0 has  invalid symbol index 11 
    /usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 1 has invalid symbol index 12 
    /usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 2 has invalid symbol index 2 
    /usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 3 has invalid symbol index 2 
    /usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 4 has invalid symbol index 11 
    /usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 5 has invalid symbol index 13 
    /usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 6 has invalid symbol index 13 
    /usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 7 has invalid symbol index 13 
    /usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 8 has invalid symbol index 2 
    /usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 9 has invalid symbol index 2 
    /usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 10 has invalid symbol index 12 
    /usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 11 has invalid symbol index 13 
    /usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 12 has invalid symbol index 13 
    /usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 13 has invalid symbol index 13 
    /usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 14 has invalid symbol index 13 
    /usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 15 has invalid symbol index 13 
    /usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 16 has invalid symbol index 13 
    /usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 17 has invalid symbol index 13 
    /usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 18 has invalid symbol index 13 
    /usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 19 has invalid symbol index 13 
/usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 20 has invalid symbol index 13 
/usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 21 has invalid symbol index 13 
/usr/bin/ld: /usr/lib/debug/usr/lib/i386-linux-gnu/crt1.o(.debug_info): relocation 22 has invalid symbol index 21 
/usr/lib/gcc/i686-linux-gnu/4.6/../../../i386-linux-gnu/crt1.o: In function `_start': 
(.text+0x18): undefined reference to `main' 
collect2: ld returned 1 exit status 

Что странно потому что кажется, что компоновщик бросает ошибки, а не компилятор. В дополнение к этому, в зависимости от того, в каком порядке программы c находятся в приведенных выше командах компиляции, либо myThreads.c удаляется, либо myThreads_test.c удаляется. Я раньше этого не видел.

Так что я попытался скомпилировать с различными строками выше. Я чувствую, что это связано с тем, как я собираюсь.

Вот myThreads.c

/*! 
@file myThreads.c 
An implementation of a package for creating, using and 
managing preemptive threads in linux. 
*/ 

// Assignment 1 
// Author: Georges Krinker 
// Student #: 260369844 
// Course: ECSE 427 (OS) 
// Note: This file has been commented using doxygen style. 
//  The API can be found at gkrinker.com/locker/OS/pa1 
//  Refer to doxygen.org for more info 

/********************************************//** 
* Includes 
***********************************************/ 


#include <signal.h> 
#include <sys/time.h> 
#include <time.h> 
#include <stdio.h>  
#include <stdlib.h>  
#include <math.h> 
#include "myThreads.h" 

/********************************************//** 
* Defines 
***********************************************/ 

#define MAX_NUMBER_OF_THREADS 20 ///< Limit on number of threads that can be created 
#define MAX_NUMBER_OF_SEMAPHORES 5 ///< Limit on number of semaphores that can be created 
#define DEFAULT_QUANTUM 250   ///< Default value for quantum if non is specified 

/** 
* Thread States 
*/ 
#define BLOCKED 0 
#define RUNNABLE 1 
#define EXIT 2 
#define RUNNING 3 
#define NOTHREAD -1 

/** 
    * Error Handling 
    */ 

#define handle_error(msg) \ 
    do { perror(msg); exit(EXIT_FAILURE); } while(0) 

/********************************************//** 
* Global Variables 
***********************************************/ 

static ucontext_t mainContext;       ///< Main context for initial thread 
static int quantum;          ///< Quantum 
static int threads_completed;       ///< 1 if all threads finished execution, ie EXIT state 
static int currentThread;        ///< ID of currently running thread 
static long dispatcherCount;       ///< Number of times the dispatcher has been called. 

static List *runQueue;         ///< Thread Run Queue. Holds indices to the tcb table 
static mythread_control_block table[MAX_NUMBER_OF_THREADS];      ///< Holds thread control blocks 
static semaphore semaphores[MAX_NUMBER_OF_SEMAPHORES];  ///< Holds semaphores 
static int tableIndex;         ///< Holds the next free table index in the table 
static int semaphoresIndex;        ///< Holds the enxt free semaphore index in the table 

static sigset_t block_alarm;       ///< The signal set that will be blocked 

/********************************************//** 
* Functions 
***********************************************/ 

/** 
* This function initializes all the global data structures for the thread system. 
* 
* Creates a new Run Queue and initilaizes the indices for both the 
* TCB table and Semaphore table to 0. It then initializes the TCB 
* and semaphore table. Finally, [TO BE COMPLETED] 
*/ 
int mythread_init(){ 
    runQueue = list_create(NULL); 
    tableIndex=0; 
    semaphoresIndex=0; 
    currentThread = -1; //No threads have been created yet. 
    int i; 
    quantum = DEFAULT_QUANTUM; 
    threads_completed = 0; 

    //Set all Thread Statuses to 'No Thread' in the TCB table 
    for(i=0;i<MAX_NUMBER_OF_THREADS;i++){ 
     table[i].status=NOTHREAD; 
    } 
    // Set all semaphores to inactive 
    int j; 
    for(j=0; j<MAX_NUMBER_OF_SEMAPHORES; j++) 
     semaphores[j].active = 0; 

    sigemptyset (&block_alarm); 
    sigaddset (&block_alarm, SIGALRM); 
} 

/** 
* This function creates a new thread. 
* 
* The function is responsible for allocating the stack and setting 
* up the user context appropriately. The newly created thread 
* starts running the threadfunc function when it starts. The 
* threadname is stored in the TCB and is printed for info 
* purposes The newly created thread is in the RUNNABLE 
* state when inserted into the system. It is added to the run queue. 
* @return the ID of the newly created thread 
* @param *threadfunc() function to be called on context switch 
* @param stacksize size of stack to be allocated to 
*/ 
int mythread_create(char *threadName, void (*threadfunc)(), int stacksize){ 

    // Handle the error if any 
    if (getcontext(&table[tableIndex].context) == -1) 
     handle_error("ERROR IN GETCONTEXT!"); 

    // Allocate a stack for the new thread and set it's return context 
    table[tableIndex].context.uc_stack.ss_size = stacksize;    //Set stack size 
    table[tableIndex].context.uc_stack.ss_sp = malloc(stacksize);  // allocate that space 
    table[tableIndex].context.uc_link = &mainContext;     // set the return context as the main Context 

    // Modify the context and fill out the thread info on the TCB table 
    makecontext(&table[tableIndex].context, threadfunc, 0);    // set the function call and 0 arguments 
    table[tableIndex].name = threadName;        // set the thread name 
    table[tableIndex].threadID = tableIndex;       // set the thread ID 
    table[tableIndex].status = RUNNABLE;        // set the thread as RUNNABLE 
    runQueue = list_append_int(runQueue, tableIndex);     // add it to the run queue 

    tableIndex++;              //point to the next free slot 

    return tableIndex-1;            // returns ID of thread 
} 
/** 
* This function is called at the end of the function that was invoked 
* by the thread. 
* 
* The function firstly masks signals, sets the status of that 
* thread to 'EXIT' and then unblocks signals before returning. 
*/ 
void mythread_exit(){ 
    sigprocmask (SIG_BLOCK, &block_alarm, NULL); 
    table[currentThread].status=EXIT; 
    sigprocmask (SIG_UNBLOCK, &block_alarm, NULL); 
} 
/** 
* Sets the quantum for the round robin (RR) scheduler. 
* 
* @param quantum_size quantum size in us 
*/ 
void set_quantum_size(int quantum_size){ 
    quantum = quantum_size; 
} 

/** 
* Schedules threads in a Round Robin fashion. 
* 
* The function starts by checking if there are no more threads to run. 
* If that is the case, it sets threads_completed to 1 so that 
* run_threads() will terminate and resume to the mainContext. 
* If there are still runnable threads, the dispatcher switches threads 
* by swapping context, and putting the expired thread at the end of the 
* run queue. Finally, if there is only one runnable thread, that thread 
* is allowed to run for one more quantum. 
*/ 
void dispatcher(){ 
    dispatcherCount++; 
    //if there are no more threads to run, and the current thread is done, set 
    // threads_completed to 1 
    if(list_empty(runQueue) && table[currentThread].status==EXIT){ 
      threads_completed=1; 
      swapcontext(&table[currentThread].context, &mainContext); 
     } 
     //else switch to the next thread 
    else if(!list_empty(runQueue)){ 
     int nextThread = list_shift_int(runQueue);       
     int tempCurrent = currentThread; 
     currentThread = nextThread; 
     // if the current thread (which is yielding to the next runnable thread) is runnable, queue it 
     //back in the runqueue 
     if(table[tempCurrent].status != EXIT && table[tempCurrent].status!=BLOCKED){ 
       runQueue = list_append_int(runQueue, tempCurrent); 
       table[tempCurrent].status = RUNNABLE; 
     } 
     table[nextThread].status = RUNNING; //set the the enxt thread to run 
     sigprocmask (SIG_BLOCK, &block_alarm, NULL); //stop the dispatcher from being called while updating timing 
     clock_gettime(CLOCK_REALTIME, &table[tempCurrent].stopTime); //record stop time 
     table[tempCurrent].elapsedTime += (double) (table[tempCurrent].stopTime.tv_nsec - table[tempCurrent].startTime.tv_nsec); //update elapsed time 
     clock_gettime(CLOCK_REALTIME, &table[currentThread].startTime);//record start timer of new thread 
       sigprocmask (SIG_UNBLOCK, &block_alarm, NULL); 
     //switch context 
     swapcontext(&table[tempCurrent].context, &table[nextThread].context); 
    } 
    else{ 
     //Keep the only thread that's runnable for 1 more quantum (do nothing!) 
    } 
} 

/** 
* The runthreads() switches control from the main thread to one of the threads in the runqueue. 
* 
* The function starts by defining a signal timer that triggers every 
* quantum usecs and calls the dispatcher. The function then starts the 
* first thread by doing a context switch. 
*/ 
void runthreads(){ 
    //Set up the signal alarm to call dispatcher() every quantum interval 
    struct itimerval tval; 
    sigset(SIGALRM, dispatcher); 
    tval.it_interval.tv_sec = 0; 
    tval.it_interval.tv_usec = quantum; 
    tval.it_value.tv_sec = 0; 
    tval.it_value.tv_usec = quantum; 
    setitimer(ITIMER_REAL, &tval, 0); 

    // If there is nothing to run, throw an error! 
    if(list_empty(runQueue)){ 
     handle_error("In runthreads: RUN QUEUE IS EMPTY!"); 
    } 
    else{ 
     int nextThread = list_shift_int(runQueue);       //find the next thread to run 
     currentThread = nextThread;           //make it the current thread 
     table[currentThread].status = RUNNING;        //set it to running 
     sigprocmask (SIG_BLOCK, &block_alarm, NULL);      //stop signal from interrupting the timing calculations 
     clock_gettime(CLOCK_REALTIME, &table[currentThread].startTime);  //record start time of the new current thread 
     sigprocmask (SIG_UNBLOCK, &block_alarm, NULL); 
     swapcontext(&mainContext, &table[nextThread].context);    //swap context 
    } 
    //only stop when there are no more threads to run! 
    while(!threads_completed); 
} 
/** 
* This function creates a semaphore and sets its initial value to the given parameter. 
* 
* @param value initial semaphore value 
*/ 
int create_semaphore(int value){ 
    // handle error as usual if value is less than 0 
    if(value < 0) 
      handle_error("semaphore initialization failed - value less than 0."); 
    else{ 
     semaphores[semaphoresIndex].initialValue = value;        //set initial value to value 
     semaphores[semaphoresIndex].value = semaphores[semaphoresIndex].initialValue; //set value 
     semaphores[semaphoresIndex].active = 1;           // make it ative now 
     semaphores[semaphoresIndex].waitingThreads = list_create(NULL);     //create a waitingThreads list for it 
    } 
    semaphoresIndex++; 

    return semaphoresIndex-1; //return ID 
} 

/** 
* Calls wait() on a Semaphore 
* 
* When a thread calls this function, the value of the semaphore is decremented. 
* If the value goes below 0, the thread is put into a WAIT state. That means 
* calling thread is taken out of the runqueue if the value of the semaphore 
* goes below 0. 
* @param semaphore index of semaphore to be manipulated in the table 
* 
*/ 
void semaphore_wait(int semaphore){ 
    long oldDispatcherCount=dispatcherCount; 
    //if trying to access a semaphore that doesn't show or is inactive handle it 
    if(semaphore > semaphoresIndex || semaphores[semaphore].active==0) 
     handle_error("Wrong semaphore index in wait()"); 

    sigprocmask (SIG_BLOCK, &block_alarm, NULL);        //mask signals for changing semaphore value (indivisibility) 
    if(--semaphores[semaphore].value<0){          // if value < 0, add thread to waiting queue 
     list_append_int(semaphores[semaphore].waitingThreads, currentThread); 
     table[currentThread].status = BLOCKED;         // change the status of the semaphore to BLOCKED 
    } 
    sigprocmask (SIG_UNBLOCK, &block_alarm, NULL);        // Re-nable signals 
    while(dispatcherCount == oldDispatcherCount);        //wait for the scheduler to switch threads (could be made more efficient) 
} 
/** 
* Calls signal() on a Semaphore 
* 
* When a thread calls this function the value of the semaphore is incremented. 
* If the value is not greater than 0, then we should at least have one thread 
* waiting on it. The thread at the top of the wait queue associated with the 
* semaphore is dequeued from the wait queue and queued in the run queue. The 
* thread state is then set to RUNNABLE. 
* @param semaphore index of semaphore to be manipulated in the table 
* 
*/ 
void semaphore_signal(int semaphore){ 
    //if trying to access a semaphore that doesn't show or is inactive handle it 
    if(semaphore > semaphoresIndex || semaphores[semaphore].active <0) 
     handle_error("Wrong semaphore index in signal()"); 

    if(++semaphores[semaphore].value<=0){          // if there are threads waiting... 
     if(list_empty(semaphores[semaphore].waitingThreads))     //contradiction! No thread waiting? Error! 
      handle_error("in Semaphore signal: there should be at least one waiting thread in semaphore"); 
     //Dequeue a waiting thread and set it to RUNNABLE. Then add it to the run queue 
     int readyThread = list_shift_int(semaphores[semaphore].waitingThreads); 
     table[readyThread].status = RUNNABLE; 
     list_append_int(runQueue, readyThread); 
    } 
} 
/** 
* Destroys a semaphore. 
* 
* A call to this function while threads are waiting on the semaphore should fail. 
* That is the removal process should fail with an appropriate error message. 
* If there are no threads waiting, this function will proceed with the removal 
* after checking whether the current value is the same as the initial value of 
* the semaphore. If the values are different, then a warning message is 
* printed before the semaphore is destroyed. 
* @param semaphore index of semaphore to be manipulated in the table 
* 
*/ 
void destroy_semaphore(int semaphore){ 
    //if trying to access a semaphore that doesn't show or is inactive handle it 
    if(semaphore > semaphoresIndex || semaphores[semaphore].active ==0) 
     handle_error("Wrong semaphore index in destroy()"); 
    //initil and final value check 
    if(semaphores[semaphore].value != semaphores[semaphore].initialValue){ 
     puts("\nWARNING: Destroying a semaphore with different initial and final values!\n"); 
    } 
    //check that there are no threads waiting on this baby 
    if(!list_empty(semaphores[semaphore].waitingThreads)){ 
     printf("Semaphore %i was not destroyed since one or more threads are waiting on it..\n",semaphore); 
    } 
    //destroy it by setting it to inactive! 
    else{ 
    semaphores[semaphore].active = 0; 
    } 
} 
/** 
* Prints the state of all threads that are maintained by the library at 
* any given time. 
* 
* For each thread, it prints the following information in a tabular 
* form: thread name, thread state (print as a string RUNNING, BLOCKED, 
* EXIT, etc), and amount of time run on CPU. 
* 
*/ 
void my_threads_state(){ 
    int i; 
    char* string; 
    for(i=0; i<MAX_NUMBER_OF_THREADS; i++){ 
     if(table[i].status != -1){ 
      switch(table[i].status){ 
       case 0: string = "BLOCKED"; break; 
       case 1: string = "RUNNABLE"; break; 
       case 3: string = "RUNNING"; break; 
       case 2: string = "EXIT"; break; 
      } 
      printf("thread name: %s with ID number: %i is in state: %s and has run for %fms.\n", 
      table[i].name, i, string, table[i].elapsedTime/1000000); 
     } 
    } 
} 

Вот myThreads.h

/*! 
@file myThreads.h 
An implementation of a package for creating, using and 
managing preemptive threads in linux. 
*/ 

// Multiple-include guard 
#ifndef __myThreads_H_ 
#define __myThreads_H_ 

#include <ucontext.h> 
#include <slack/std.h> 
#include <slack/list.h> 

/********************************************//** 
* Structures 
***********************************************/ 

/*! \brief Structure that represents the thread control block (TCB). 
*/ 

typedef struct _mythread_control_block { 
    ucontext_t context; 
    char *name; 
    int threadID; //Between 0-# of Threads 
    int status; // Any of the above defines 
    struct timespec startTime; //when it was created 
    struct timespec stopTime; // when it was stopped 
    double elapsedTime; //start-stop in ns 

}mythread_control_block; 

typedef struct _mythread_semaphore{ 
    int value; 
    int initialValue; 
    int active; 
    List *waitingThreads; // holds indices to the semaphores table 
}semaphore; 

/********************************************//** 
* Functions 
***********************************************/ 

/** 
* This function initializes all the global data structures for the thread system. 
* 
* Creates a new Run Queue and initilaizes the indices for both the 
* TCB table and Semaphore table to 0. It then initializes the TCB 
* and semaphore table. Finally, [TO BE COMPLETED] 
*/ 
int init_my_threads(); 
/** 
* This function creates a new thread. 
* 
* The function is responsible for allocating the stack and setting 
* up the user context appropriately. The newly created thread 
* starts running the threadfunc function when it starts. The 
* threadname is stored in the TCB and is printed for info 
* purposes The newly created thread is in the RUNNABLE 
* state when inserted into the system. It is added to the run queue. 
* @return the ID of the newly created thread 
* @param *threadfunc() function to be called on context switch 
* @param stacksize size of stack to be allocated to 
*/ 
int mythread_create(char *threadName, void (*threadfunc)(), int stacksize); 

/** 
* This function is called at the end of the function that was invoked 
* by the thread. 
* 
* The function firstly masks signals, sets the status of that 
* thread to 'EXIT' and then unblocks signals before returning. 
*/ 
void mythread_exit(); 

/** 
* Sets the quantum for the round robin (RR) scheduler. 
* 
* @param quantum_size quantum size in us 
*/ 
void set_quantum_size(int quantum_size); 

/** 
* Schedules threads in a Round Robin fashion. 
* 
* The function starts by checking if there are no more threads to run. 
* If that is the case, it sets threads_completed to 1 so that 
* run_threads() will terminate and resume to the mainContext. 
* If there are still runnable threads, the dispatcher switches threads 
* by swapping context, and putting the expired thread at the end of the 
* run queue. Finally, if there is only one runnable thread, that thread 
* is allowed to run for one more quantum. 
*/ 
void dispatcher(); 

/** 
* The runthreads() switches control from the main thread to one of the threads in the runqueue. 
* 
* The function starts by defining a signal timer that triggers every 
* quantum usecs and calls the dispatcher. The function then starts the 
* first thread by doing a context switch. 
*/ 
void runthreads(); 

/** 
* This function creates a semaphore and sets its initial value to the given parameter. 
* 
* @param value initial semaphore value 
*/ 
int create_semaphore(int value); 

/** 
* Calls wait() on a Semaphore 
* 
* When a thread calls this function, the value of the semaphore is decremented. 
* If the value goes below 0, the thread is put into a WAIT state. That means 
* calling thread is taken out of the runqueue if the value of the semaphore 
* goes below 0. 
* @param semaphore index of semaphore to be manipulated in the table 
* 
*/ 
void semaphore_wait(int semaphore); 

/** 
* Calls signal() on a Semaphore 
* 
* When a thread calls this function the value of the semaphore is incremented. 
* If the value is not greater than 0, then we should at least have one thread 
* waiting on it. The thread at the top of the wait queue associated with the 
* semaphore is dequeued from the wait queue and queued in the run queue. The 
* thread state is then set to RUNNABLE. 
* @param semaphore index of semaphore to be manipulated in the table 
* 
*/ 
void semaphore_signal(int semaphore); 

/** 
* Prints the state of all threads that are maintained by the library at 
* any given time. 
* 
* For each thread, it prints the following information in a tabular 
* form: thread name, thread state (print as a string RUNNING, BLOCKED, 
* EXIT, etc), and amount of time run on CPU. 
* 
*/ 
void my_threads_state(); 

#endif 

Наконец, здесь myThreads_test.c

/*! 
@file myThreads_test.c 
A test program for testing myThreads.c 
*/ 

// Assignment 1 
// Author: Georges Krinker 
// Student #: 260369844 
// Course: ECSE 427 (OS) 
// Note: This file has been commented using doxygen style. 
//  The API can be found at gkrinker.com/locker/OS/pa1 
//  Refer to doxygen.org for more info 

/********************************************//** 
* Includes 
***********************************************/ 

#include <stdio.h>  
#include <stdlib.h>  
#include "myThreads.h" 

/********************************************//** 
* Global Variables 
***********************************************/ 

int mutex;           //Mutex used by shared resources 

int a; 
int b; 
int mult; 

void multiply() { 
    int i; 
    for(i=0;i<1000;++i){ 
    semaphore_wait(mutex); 
    mult=mult+(a*b); 
    a++; 
    b++; 
    semaphore_signal(mutex);  
    } 
    mythread_exit(); 
} 

int main(){ 
    a=0; 
    b=0; 
    mult=0; 
    mutex=create_semaphore(1); 

    int threads = 12;        // How many threads are to be created 
    char* names[] = { 
     "thread 0", 
     "thread 1", 
     "thread 2", 
     "thread 3", 
     "thread 4", 
     "thread 5", 
     "thread 6", 
     "thread 7", 
     "thread 8", 
     "thread 9", 
     "thread 10", 
     "thread 11" 
    }; 

    mythread_init();        // Initialize Package 

    set_quantum_size(50);       // set quantum to 50 

    //Create threads 

    int i=0; 
    int dummy = 0; 

    for(i=0; i<threads; i++) 
    { 
     dummy=mythread_create(names[i], (void *) &multiply, 100); 
    } 

    runthreads();        // Run threads 

    my_threads_state();       // See state 

    printf("The value of mult is %d\n", mult); 

    return 0; 

} 

ответ

2

-o означает, что вы хотите, чтобы указать выходной файл. Таким образом,

gcc -o myThreads.c myThreads_test.c ... 

не имеет смысла. Попробуйте скомпилировать два файла отдельно:

gcc myThreads.c -o myThreads ... 
gcc myThreads_test.c -o myThreads_test ... 

где myThreads и myThreads_test будут исполняемыми имена файлов.

1

gcc -o myThreads_test.c myThreads.c компилирует myThreads.c и сохраняет двоичный выход в myThreads_test.c. Итак, ваш myThreads_test.c теперь является двоичным файлом! И наоборот, для вашего другого заявления о компиляции. Вот почему пострадает один из ваших файлов .c.

Просто измените компиляции заявление:

gcc -o myThreads myThreads_test.c myThreads.c -DHAVE_PTHREAD_RWLOCK=1 -lslack -lrt

Смежные вопросы