Здравствуйте, icWasya, Вы писали:
W>Здравствуйте, Nick-77, Вы писали:
W>...
N7>>т.е. вроде как несмотря на то, что формально tmp и её адреса после выхода из f не существует, реально стек ещё никто не успел (?) испортить и содержимое верное.
N7>>Хотелось бы узнать у господ знатоков, насколько корректно подобное допущение.
Еще бывает что стек растёт в другую сторону на некоторых архитектурах.
| | Скрытый текст |
| | // ptsk.h : popup multitasking
#ifndef __PTSK_H__
#define __PTSK_H__
#include <setjmp.h>
#include "ticks.h" // any real time clock
#ifdef __cplusplus
extern "C" {
#endif
typedef struct ptsk_tcb_tag {
void (*task)(void*);
void *args;
int stack_size;
jmp_buf ctx;
struct ptsk_tcb_tag* next;
struct ptsk_tcb_tag* prev;
} ptsk_tcb_t;
void ptsk_init(void);
void ptsk_done(void);
void ptsk_idle(void); // give control to next task
void ptsk_addtask(ptsk_tcb_t *task); // create new task
void ptsk_deltask(ptsk_tcb_t *task); // if current it'll die
void ptsk_die(void); // kill current task
ptsk_tcb_t* ptsk_getcurrent(); // get current task descriptor
extern int ptsk_active;
void ptsk_sleep(ticks_t ticks);
void ptsk_sleep_till(ticks_t time);
/*
usage:
#include <stdio.h>
#include "ptsk.h"
void task1(void* arg) {
for(int i=0;i<=9;++i) {
printf("task1 \ti=%d\n",i);
ptsk_idle();
}
}
void task2(void* arg) {
for(int i=0;i<=7;++i) {
printf("task2 \t\ti=%d\n",i);
ptsk_sleep(500);
}
}
void task3(void* arg) {
for(int i=0;i<=5;++i) {
printf("task3 \t\t\ti=%d\n",i);
ptsk_sleep(1000);
}
}
ptsk_tcb_t t1={task1,(void*)1,1024};
ptsk_tcb_t t2={task2,(void*)2,1024};
ptsk_tcb_t t3={task3,(void*)3,1024};
void main() {
ptsk_init();
ptsk_addtask(&t1);
ptsk_addtask(&t2);
ptsk_addtask(&t3);
ptsk_idle();
ptsk_done();
}
*/
#ifdef __cplusplus
}
#endif
#endif // __PTSK_H__
// ptsk.c
#include "ptsk.h"
#ifdef __cplusplus
extern "C" {
#endif
enum {
PTSK_1ST =0,
PTSK_WAKE=1,
PTSK_NEW =2,
PTSK_RET =3
};
int ptsk_active=0;
ptsk_tcb_t* ptsk_head;
ptsk_tcb_t* ptsk_tail;
ptsk_tcb_t* ptsk_curr;
jmp_buf ptsk_last;
jmp_buf ptsk_main;
void ptsk_init(void) {
ptsk_active=0;
ptsk_head=ptsk_tail=ptsk_curr=0;
}
void ptsk_done(void) {
if (ptsk_active) longjmp(ptsk_main,PTSK_RET);
}
void ptsk_panic(void) {
// exit(0);
for(;;) {}
}
void ptsk_switch(void) {
ptsk_curr=ptsk_curr->next;
if (!ptsk_curr) {
ptsk_curr=ptsk_head;
if (!ptsk_curr) ptsk_done();
}
longjmp(ptsk_curr->ctx,PTSK_WAKE);
}
void ptsk_die(void) {
if (!ptsk_curr) { ptsk_done(); ptsk_panic(); return; } // panic
if (ptsk_curr->prev) ptsk_curr->prev->next=ptsk_curr->next; else ptsk_head=ptsk_curr->next;
if (ptsk_curr->next) ptsk_curr->next->prev=ptsk_curr->prev; else ptsk_tail=ptsk_curr->prev;
ptsk_switch();
}
void ptsk_deltask(ptsk_tcb_t *task) {
if (ptsk_curr==task) ptsk_die();
if (task->prev) task->prev->next=task->next; else ptsk_head=task->next;
if (task->next) task->next->prev=task->prev; else ptsk_tail=task->prev;
}
int ptsk_stackalloc(int arg) {
volatile int dummy; ptsk_tcb_t* tsk; int sz;
static int* stk;
if (arg==1) stk=(int*)&dummy;
sz=(int*)&dummy-stk; if (sz<0) sz=-sz;
if (sz<ptsk_tail->stack_size) ptsk_stackalloc(0);
tsk=ptsk_tail;
if (setjmp(ptsk_last)==PTSK_NEW) ptsk_stackalloc(1);
switch(setjmp(tsk->ctx)) {
case PTSK_1ST: longjmp(ptsk_main,PTSK_RET);
case PTSK_WAKE: tsk->task(tsk->args);
}
ptsk_die(); return dummy;
}
void ptsk_addtask(ptsk_tcb_t *task) {
ptsk_tcb_t* last;
last=ptsk_tail;
task->prev=ptsk_tail;
task->next=0;
if (ptsk_tail) ptsk_tail->next=task; else ptsk_head=task;
ptsk_tail=task;
switch(setjmp(ptsk_main)) {
case PTSK_1ST: if (last) longjmp(ptsk_last,PTSK_NEW); else ptsk_stackalloc(1);
//case PTSK_RET: break;
}
}
void ptsk_idle(void) {
if (!ptsk_curr) {
ptsk_curr=ptsk_head; if (!ptsk_curr) return;
ptsk_active=1;
switch(setjmp(ptsk_main)) {
case PTSK_1ST: ptsk_curr->task(ptsk_curr->args); ptsk_die();
//case PTSK_RET: break;
}
ptsk_active=0;
return;
}
switch(setjmp(ptsk_curr->ctx)) {
case PTSK_1ST: ptsk_switch();
//case PTSK_WAKE: break;
}
}
ptsk_tcb_t* ptsk_getcurrent() {
return ptsk_curr;
}
void ptsk_sleep_till(ticks_t time) {
do {
ptsk_idle();
} while(time-getticks()>0);
}
void ptsk_sleep(ticks_t ticks) {
ptsk_sleep_till(getticks()+ticks);
}
#ifdef __cplusplus
}
#endif
|
| | |
W>Если после выхода из функции произойдёт прерывание
, то его обработчик всё затрёт
.
Это только не в защищённых режимах такая фигня. Бывает