MUP1+Øvelse+7+API+II

toc =The OS API II=

Linux-edition
Download:

linuxwrap.h
Det er ikke meget ide i at paste hele filen da dens interface er præcis det samme som win32wrap.h. Download ovenstående fil hvis du vil se den i sin helhed. Det er dog værd at nævne at der er blevet defineret nogle macroer: code format="cpp" //sched_get_priority_min(SCHED_RR) = 1 //sched_get_priority_max(SCHED_RR) = 99 code PTHREAD_PRIORITY værdierne er fundet ved at finde ud af hvad funktionerne returnered, hvorefter prioritets niveauerne blev baseret derpå.
 * 1) define PTHREAD_PRIORITY_LOWEST 		1
 * 2) define PTHREAD_PRIORITY_BELOW_NORMAL 	25
 * 3) define PTHREAD_PRIORITY_NORMAL 		50
 * 4) define PTHREAD_PRIORITY_ABOVE_NORMAL 	75
 * 5) define PTHREAD_PRIORITY_HIGHEST 		99
 * 6) define DWORD unsigned int
 * 7) define LONG long int

Thread konstruktøren blev også overloaded med det formål at tråde der ikke ønskede at ændre prioritet ikke behøver //root// rettigheder. code format="cpp" Thread(std::string nme = "") : priority(PRIORITY_NORMAL), name(nme), rootMode(false) {} code

Thread.cpp
Det er meget vigtigt at threadMapper er erklæret som da funktionen får en statisk plads i memory og derfor kan linkes til via en pointer. code format="cpp"
 * 1) include "linuxwrap.h"
 * 2) include
 * 3) include

//--- // CLASS: Thread //--- Thread::Thread(Thread::ThreadPriority pri, std::string nme) : priority(pri), name(nme), rootMode(true) {	if(geteuid!=0) {		printf("You must have admin rights to use class Thread. Rerun program as root\n"); exit(1); }

}

Thread::~Thread {}

void Thread::start {	pthread_attr_t attr; sched_param sched_p;

pthread_attr_init(&attr);										// Init attr if (rootMode) {		pthread_attr_setschedpolicy(&attr, SCHED_RR);					// Set RR scheduling (RT, timesliced) pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);	// Create thread with explicit (non-inherited) scheduling - setting priority will not work otherwise! sched_p.sched_priority = (int)priority;							// Set priority pthread_attr_setschedparam(&attr, &sched_p);					// Use the priority }	if ((errno = pthread_create(&threadId, &attr, threadMapper, (void*)this)) != 0) {		linuxwrap::reportError("Thread start"); exit(1); } }

void* Thread::threadMapper(void* p) { ((Thread*)p)->run; return 0; }

bool Thread::setPriority(Thread::ThreadPriority prio) {	priority = prio; if ((errno = pthread_setschedprio(threadId, prio)) == 0) return true; linuxwrap::reportError("Thread setPriority"); return false; }

Thread::ThreadPriority Thread::getPriority {	return priority; }

std::string Thread::getName {	return name; } code

Semaphores.cpp
code format="cpp"
 * 1) include "linuxwrap.h"
 * 2) include 
 * 3) include

//==================================================== //METHOD : CountingSemaphore ctor //DESCR. : //==================================================== CountingSemaphore::CountingSemaphore(unsigned init) {	//assert(init < SEM_VALUE_MAX); // WTF! SEM_VALUE_MAX is undefined... http://www.sbin.org/doc/glibc/libc_34.html if (sem_init(&id, NULL, init) == -1) {		linuxwrap::reportError("CountingSemapore constructor"); exit(1); }

}

//==================================================== //METHOD : dtor //DESCR. : //==================================================== CountingSemaphore::~CountingSemaphore {	if (sem_destroy(&id) == -1) linuxwrap::reportError("CountingSemapore destructor"); }

//==================================================== //METHOD : wait //DESCR. : //==================================================== void CountingSemaphore::wait {	if (sem_wait(&id) == -1) linuxwrap::reportError("CountingSemapore wait"); }

//==================================================== //METHOD : signal //DESCR. : //==================================================== void CountingSemaphore::signal {	if (sem_post(&id) == -1) linuxwrap::reportError("CountingSemapore signal"); }

//==================================================== //METHOD : Mutex ctor //DESCR. : //==================================================== Mutex::Mutex {	if ((errno = pthread_mutex_init(&id, NULL)) != 0) {		linuxwrap::reportError("Mutex constructor"); exit(1); } }

//==================================================== //METHOD : Mutex dtor //DESCR. : //==================================================== Mutex::~Mutex {	if ((errno = pthread_mutex_destroy(&id)) != 0) linuxwrap::reportError("Mutex destructor"); }

//==================================================== //METHOD : signal //DESCR. : //==================================================== void Mutex::signal {	if ((errno = pthread_mutex_unlock(&id)) != 0) linuxwrap::reportError("Mutex signal"); }

//==================================================== //METHOD : wait //DESCR. : //==================================================== void Mutex::wait {	if ((errno = pthread_mutex_lock(&id)) != 0) linuxwrap::reportError("Mutex wait"); } code

ScopeLocker.cpp
code format="cpp"
 * 1) include "linuxwrap.h"

ScopedLocker::ScopedLocker(Mutex &m) : mutex(m) {	mutex.wait; }

ScopedLocker::~ScopedLocker {	mutex.signal; } code

SleepTimer
code format="cpp" class SleepTimer { public: SleepTimer {} ~SleepTimer {} void sleep(DWORD ms) {		usleep(ms*1000); } }; code

Mailbox
Mailbox klassen er lavet om til at bruge message queues. code format="cpp" //==================================================== //CLASS : 	MessageHandling //DESCR.: //==================================================== class MessageHandling { public: template static ssize_t sendMsg(int msgQId, const Msg& data, long int type = 1, int flag = 0) {       MsgWrapper msg; msg.type = type; msg.data = data; return msgsnd(msgQId, (void*) &msg, sizeof(data), flag); }   template static ssize_t receiveMsg(int msgQId, Msg& data, long int type = 0, int flag = 0) {       MsgWrapper msg; ssize_t recvSize = msgrcv(msgQId, (void*) &msg, sizeof(data), type, flag); data = msg.data; return recvSize; } private: template struct MsgWrapper { public: long int type; Msg data; }; };

//==================================================== //CLASS : 	Mailbox //DESCR.: //==================================================== template class Mailbox { public: Mailbox(const LONG cap) : capacity(cap) {		getSemaphore = new CountingSemaphore(0);   // Counts number of items in mailbox putSemaphore = new CountingSemaphore(cap); // Counts number of free slots in mailbox key = msgget(IPC_PRIVATE, 0666 | IPC_CREAT); // Create message queue (IPC_PRIVATE is flag for new queue) if (key == -1) {			linuxwrap::reportError("Mailbox constructor"); exit(1); }	}

~Mailbox {		if (msgctl(key, IPC_RMID, NULL) == -1) // delete message queue linuxwrap::reportError("Mailbox destructor"); delete putSemaphore; delete getSemaphore; }

void put(const Item& n)	{ putSemaphore->wait; MessageHandling::sendMsg(key, n); getSemaphore->signal; }

Item get {		Item *obj = new Item; getSemaphore->wait; MessageHandling::receiveMsg(key, *obj); putSemaphore->signal; return *obj; }

private: LONG capacity; CountingSemaphore* getSemaphore; CountingSemaphore* putSemaphore; key_t key; }; code

Test
Test program: (//udleveret//)

Udskrift
//**Husk** at køre programmet som root ellers har vi ikke rettigheder til at ændre prioritet på trådene.// code stud@ubuntu:~/iha/3/mup1/workspace/linuxwrap/Debug$ sudo ./linuxwrap [sudo] password for stud: NP: 0 VP: 0 NP: 456476382 VP: 0 NP: 891521086 VP: 0 NP: 1326135738 VP: 0 NP: 1759832627 VP: 0 NP: 435725161 VP: 0 NP: 435985744 VP: 0 NP: 868827683 VP: 0 NP: 435182074 VP: 0 NP: 868729801 VP: 0 4 NP: 401193140 VP: 457804476 NP: 0 VP: 915962447 NP: 0 VP: 456369646 NP: 0 VP: 914761568 NP: 0 VP: 1372076833 NP: 0 VP: 1828659288 NP: 0 VP: 456723531 NP: 0 VP: 456999980 NP: 0 VP: 914105923 NP: 0 VP: 456379368 NP: 0 VP: 869439042 2 NP: 521548313 VP: 1183189538 NP: 729296941 VP: 1412222311 NP: 955588779 VP: 1619662819 NP: 227822109 VP: 1826028635 NP: 437856653 VP: 2052858270 NP: 207404726 VP: 230112411 NP: 223488188 VP: 210548176 NP: 452139787 VP: 206399355 NP: 663265495 VP: 429488712 NP: 869427220 VP: 227657630 NP: 1091389970 VP: 439947228 code I starten bliver den lavest prioriterede tråd VP kvalt af NP. Det skifter da VP får højest prioritet og endelig da de begge har lige høj prioritet får de begge lov at kører.

linuxwrap library
Vi fulgte guiden "Fremstilling af biblioteker til OS API".

Test af Øvelse 6.1 samt Øvelse 6.2
Udskifter med  i main.cpp, kompilere og kører på både host og target.

Konklusion: Det virker.