Hi all,
Currently I'm working on a stackless python 2.6.2 implementation on a single
threaded embedded device. The application running inserts and removes tasklets
asynchronously based on hardware callbacks. I am trying to write a scheduling
loop in C that will reinsert tasklets to the run queue and call
stackless.run(100). The problem that I am running into is that _Py_Ticker
value never gets reset. This causes every single call to stackless.run(100)
after the first call will hit the stackless_interupt_call in ceval.c line 2995,
and no more code gets executed. My scheduling routine is attached in the file
my_scheduler.c in the method scheduler_run(). I have been using the
test_scheduler.py script to test my module. I also wrote a test script called
test_stackless that mimics the behavior that I'm trying to accomplish. In
addition, I also verified that I got the same result when I moved the test()
method to its own module. I am missing a step in setting up the call to
stackless.schedule() in my c code?
#ifndef _LINKEDLIST_H_
#define _LINKEDLIST_H_
typedef struct __list_node
{
void* Data;
struct __list_node* Next;
} ListNode;
int LinkedListEpoch(void);
ListNode *list_create(void);
int list_add(ListNode *head, void* listEntry);
int list_remove(ListNode *head, void* listEntry);
#endif
#include "Python.h"
#include "stackless_api.h"
#include "LinkedList.h"
PyObject *my_scheduler_error;
ListNode *ReinsertPendingPointer = NULL;
ListNode *list_create(void)
{
ListNode* node = NULL;
node = malloc(sizeof(ListNode));
if(node == NULL)
{
errno = ENOMEM;
return -1;
}
node->Data = NULL;
node->Next = NULL;
return node;
}
int list_add(ListNode *head, void* listEntry)
{
ListNode* node;
if(head == NULL)
{
errno = EINVAL;
return -1;
}
node = head;
while(node->Next != NULL)
{
node = node->Next;
}
// Create and insert the new node into the linked-list
node->Next = malloc(sizeof(ListNode));
if(node->Next == NULL)
{
errno = ENOMEM;
return -1;
}
node = node->Next;
node->Data = listEntry;
node->Next = NULL;
/*===== Add the pending structure to the list -----*/
return 0;
}
int list_remove(ListNode *head, void* listEntry)
{
ListNode* prev;
ListNode* current;
prev = head;
current = prev->Next;
while(current != NULL && current->Data != listEntry)
{
prev = current;
current = current->Next;
}
if(current == NULL || current->Data != listEntry)
{
return -1;
}
prev->Next = current->Next;
free(current);
return 0;
}
void ReinsertPendingScripts(void)
{
ListNode *prevNode = NULL;
ListNode *currentNode = NULL;
PyTaskletObject *tasklet = NULL;
if(ReinsertPendingPointer != NULL)
{
prevNode = ReinsertPendingPointer;
currentNode = prevNode->Next;
while(currentNode != NULL)
{
tasklet = (PyTaskletObject *)currentNode->Data;
slp_current_insert(tasklet);
Py_DECREF(tasklet);
list_remove(ReinsertPendingPointer, tasklet);
currentNode->Data = NULL;
currentNode = prevNode;
prevNode = currentNode;
currentNode = currentNode->Next;
}
}
else
{
ReinsertPendingPointer = list_create();
}
}
static PyObject * scheduler_run(PyObject *self, PyObject *args)
{
int retval = -1;
PyObject *RetTasklet = NULL;
PyObject *module_dict=NULL;
/* Declarations for Stackless Module */
PyObject *stacklessmod=NULL;
PyObject *sm_dict=NULL;
PyObject *sm_runcall=NULL;
do
{
/*----- Calls to get the stackless.run(100) call in the namespace -----*/
stacklessmod = PyImport_AddModule("stackless");
if(stacklessmod == NULL)
{
break;
}
sm_dict = PyModule_GetDict(stacklessmod);
if(sm_dict == NULL)
{
break;
}
sm_runcall = PyDict_GetItemString(sm_dict, "run");
if(sm_runcall == NULL)
{
break;
}
while(1)
{
ReinsertPendingScripts();
// run next tasklet for 100
RetTasklet = PyEval_CallFunction(sm_runcall, "(i)", 100);
if(RetTasklet == NULL)
{
PyErr_Print();
}
else if(RetTasklet != Py_None)
{
Py_INCREF(RetTasklet);
list_add(ReinsertPendingPointer, RetTasklet);
}
}
/* This shouldn't happen, but need to handle the case */
Py_XDECREF(sm_runcall);
Py_XDECREF(sm_dict);
Py_XDECREF(stacklessmod);
}while(0);
}
static PyMethodDef my_scheduler_methods[] = {
{"run",scheduler_run,METH_VARARGS
,"Run my scheduler"},
{NULL,NULL,0,NULL}
};
PyMODINIT_FUNC
initmy_scheduler(void)
{
PyObject *m;
m = Py_InitModule("my_scheduler",my_scheduler_methods);
if(my_scheduler_error == NULL) {
my_scheduler_error = PyErr_NewException("my_scheduler.error", NULL, NULL);
if (my_scheduler_error == NULL)
return;
}
Py_INCREF(my_scheduler_error);
PyModule_AddObject(m, "error", my_scheduler_error);
}
import stackless
import my_scheduler
def a():
while 1:
print 'test a'
def b():
while 1:
print 'test b'
stackless.tasklet(a)()
stackless.tasklet(b)()
my_scheduler.run()
import stackless
def test_schedule():
while 1:
t=stackless.run(100)
t.insert()
def a():
while 1:
print 'test a'
def b():
while 1:
print 'test b'
stackless.tasklet(a)()
stackless.tasklet(b)()
test_schedule()
_______________________________________________
Stackless mailing list
[email protected]
http://www.stackless.com/mailman/listinfo/stackless