Added flag "-debug" to charmc for usage with charmdebug.
authorFilippo Gioachin <gioachin@illinois.edu>
Wed, 26 Mar 2008 03:21:29 +0000 (03:21 +0000)
committerFilippo Gioachin <gioachin@illinois.edu>
Wed, 26 Mar 2008 03:21:29 +0000 (03:21 +0000)
Some work done on CmiReduce to make it possible to have concurrent reductions.
Added memory tagging by chare ID in charmdebug.
Fixed breakpointing with charmdebug: now each entry point is defined by its sequential index in the EP table (before a string match was performed).
Added stepping: delivery of a single message in the queue. Also, all the system entry methods are currently always executed, and never get buffered by charmdebug (they can still breakpoint if the user so chooses).
Fixed race condition in python interface. To do that the interface itself has been modified, in particular with regard to high-level python. Python is now more flexible and it allows any chare collection to be "python" and receive requests. The replies are reduced to a PythonCCS mainchare which will handle the socket.
The python directory has now another module (charmdebug-python) for usage by charmdebug introspection code.

29 files changed:
src/ck-core/ck.C
src/ck-core/ckcallback.h
src/ck-core/debug-charm.C
src/ck-core/debug-charm.h
src/ck-core/init.C
src/ck-perf/trace-common.C
src/ck-perf/trace-memory.C
src/ck-perf/trace-memory.h
src/ck-perf/trace.h
src/ck-perf/tracec.C
src/ck-perf/tracec.h
src/conv-ccs/conv-ccs.c
src/conv-core/convcore.c
src/conv-core/converse.h
src/conv-core/debug-conv.c
src/conv-core/debug-conv.h
src/conv-core/memory-charmdebug.c
src/conv-core/memory.c
src/libs/ck-libs/pythonCCS/Makefile
src/libs/ck-libs/pythonCCS/PythonCCS.C
src/libs/ck-libs/pythonCCS/PythonCCS.ci
src/libs/ck-libs/pythonCCS/PythonCCS.h
src/libs/ck-libs/pythonCCS/charmdebug-python.C [new file with mode: 0644]
src/libs/ck-libs/pythonCCS/charmdebug-python.ci [new file with mode: 0644]
src/scripts/Makefile
src/scripts/charmc
src/scripts/configure.in
src/scripts/conv-autoconfig.h.in
src/xlat-i/xi-symbol.C

index 6506cd4ec30422a3d663cdfd79c14fecdefaecaa..040b1afdbdd8ba45b3b2882b53d3479c5af3b83b 100644 (file)
@@ -1143,6 +1143,10 @@ void CkSendMsgInline(int entryIndex, void *msg, const CkChareID *pCid, int opts)
     if(!CmiNodeAlive(CkMyPe())){
        return;
     }
+#ifndef CMK_OPTIMIZE
+    //Just in case we need to breakpoint or use the envelope in some way
+    _prepareMsg(entryIndex,msg,pCid);
+#endif
                //Just directly call the chare (skip QD handling & scheduler)
     register envelope *env = UsrToEnv(msg);
     if (env->isPacked()) CkUnpackMessage(&env);
index fe1025661a54f6236cfbc3b8d7b1aca788a09258..edf870c0436d3f3cac124fba7a374342a9396be3 100644 (file)
@@ -162,13 +162,19 @@ PUPbytes(CkCallback) //FIXME: write a real pup routine
  *   library can't or won't call "thread_delay".
  * The return value is lost, so your library needs to call
  *   thread_delay itself if you want a return value.
+ * Modification Filippo: Passing in an pointer argument, the return
+ *   value will be stored in that pointer 
  */
 class CkCallbackResumeThread : public CkCallback {
+ protected: void ** result;
  public:
        CkCallbackResumeThread(void)
-               :CkCallback(resumeThread) {}
+               :CkCallback(resumeThread) { result = NULL; }
+       CkCallbackResumeThread(void * &ptr)
+           :CkCallback(resumeThread) { result = &ptr; }
        ~CkCallbackResumeThread(void) {
-               thread_delay(); //<- block thread here if it hasn't already
+           void * res = thread_delay(); //<- block thread here if it hasn't already
+           if (result != NULL) *result = res;
        }
 };
 
index b11b330956dd30dde813242be6906705c65a7cfa..7e928d65e6a123d15fa48c13bbaf1bd437b113d1 100644 (file)
@@ -69,7 +69,7 @@ public:
    {
      if (cur>=lo && cur<hi) 
      { /* This element is in our range-- look it up */
-       dest->add(cur,mgr->lookup(loc.getIndex()));
+       dest->add(cur,mgr->lookup(loc.getIndex()),mgr->getGroupID().idx);
      }
      cur++;
    }
@@ -97,16 +97,16 @@ public:
      int numGroups=CkpvAccess(_groupIDTable)->size();
      for(int i=0;i<numGroups;i++) {
         IrrGroup *obj = CkpvAccess(_groupTable)->find((*CkpvAccess(_groupIDTable))[i]).getObj();
-       if (obj->isArrMgr()) 
-       { /* This is an array manager: examine its array elements */
+       /*if (obj->isArrMgr()) 
+       { / * This is an array manager: examine its array elements * /
          CkArray *mgr=(CkArray *)obj;
           CkArrayElementRangeIterator<T> ait(dest,lo,hi);
          ait.iterate(cur, mgr);
           cur+=ait.getCount();
-       } else {
-          dest->add(cur,obj);
+       } else {*/
+          dest->add(cur,obj,i);
           cur++;
-        }
+        //}
      }
    }
    
@@ -115,7 +115,7 @@ public:
 };
 
 class ignoreAdd {
-public: void add(int cur,Chare *elt) {}
+public: void add(int cur,Chare *elt,int group) {}
 };
 
 /** Examine all the objects on the server returning the name */
@@ -134,7 +134,7 @@ public:
     CkObjectRangeIterator<CpdList_objectNames> it(this,req.lo,req.hi);
     it.iterate(); // calls "add" for in-range elements
   }
-  void add(int cur, Chare *obj) {
+  void add(int cur, Chare *obj, int group) {
     PUP::er &p=*pp;
     beginItem(p,cur);
     p.comment("id");
@@ -143,6 +143,7 @@ public:
     CkAssert(s > 0);
     p(n,s);
     free(n);
+    PUPn(group);
     p.comment("name");
     n=obj->ckDebugChareName();
     p(n,strlen(n));
@@ -168,7 +169,7 @@ public:
     CkObjectRangeIterator<CpdList_object> it(this,req.lo,req.hi);
     it.iterate(); // calls "add" for in-range elements;
   }
-  void add(int cur, Chare *obj) {
+  void add(int cur, Chare *obj, int group) {
     PUP::er &p=*pp;
     CpdListItemsRequest &req=*reqq;
     char *n = (char *)malloc(30);
@@ -203,7 +204,7 @@ public:
     CkArrayElementRangeIterator<CpdList_arrayElementNames> it(this,req.lo,req.hi);
     it.iterate(); // calls "add" for in-range elements
   }
-  void add(int cur,Chare *e) 
+  void add(int cur,Chare *e,int group
   { // Just grab the name and nothing else:
     ArrayElement *elt = (ArrayElement*)e;
          PUP::er &p=*pp;
@@ -230,7 +231,7 @@ public:
     CkArrayElementRangeIterator<CpdList_arrayElements> it(this,req.lo,req.hi);
     it.iterate(); // calls "add" for in-range elements
   }
-  void add(int cur, Chare *e) 
+  void add(int cur, Chare *e, int group
   { // Pup the element data
     ArrayElement *elt = (ArrayElement*)e;
     PUP::er &p=*pp;
@@ -274,6 +275,7 @@ void hostInfo(void *itemIter, pup_er pp, CpdListItemsRequest *req) {
 
 /************ Message CPD Lists ****************/
 CpvCExtern(void *,debugQueue);
+CpvCExtern(int, skipBreakpoint);
 
 // Interpret data in a message in a user-friendly way.
 //  Ignores most of the envelope fields used by CkPupMessage,
@@ -310,6 +312,8 @@ void CpdPupMessage(PUP::er &p, void *msg)
   p.synchronize(PUP::sync_end_object);
 }
 
+CpvStaticDeclare(void *, lastBreakPointMsg);
+
 //Cpd Lists for local and scheduler queues
 class CpdList_localQ : public CpdListAccessor {
 
@@ -320,39 +324,53 @@ public:
     int x = CdsFifo_Length((CdsFifo)(CpvAccess(debugQueue)));
     //CmiPrintf("*******Returning fifo length %d*********\n", x);
     //return CdsFifo_Length((CdsFifo)(CpvAccess(CmiLocalQueue)));
+    if (CpvAccess(lastBreakPointMsg) != NULL) x++;
     return x;
   }
   virtual void pup(PUP::er &p, CpdListItemsRequest &req) {
     int length = CdsFifo_Length((CdsFifo)(CpvAccess(debugQueue)));
     void ** messages = CdsFifo_Enumerate(CpvAccess(debugQueue));
     int curObj=0;
+
+    if (CpvAccess(lastBreakPointMsg) != NULL) {
+      beginItem(p, -1);
+      envelope *env=(envelope *)UsrToEnv(CpvAccess(lastBreakPointMsg));
+      p.comment("name");
+      char *type="Breakpoint";
+      p(type,strlen(type));
+      p.comment("charmMsg");
+      p.synchronize(PUP::sync_begin_object);
+      CkUnpackMessage(&env);
+      CpdPupMessage(p, EnvToUsr(env));
+      p.synchronize(PUP::sync_end_object);
+    }
     
     for(curObj=req.lo; curObj<req.hi; curObj++)
-    if ((curObj>=0) && (curObj<length))
-    {
+      if ((curObj>=0) && (curObj<length))
+      {
         beginItem(p,curObj);
         void *msg=messages[curObj]; /* converse message */
-       int isCharm=0;
+        int isCharm=0;
         const char *type="Converse";
         p.comment("name");
         char name[128];
-       if (CmiGetHandler(msg)==_charmHandlerIdx) {isCharm=1; type="Local Charm";}
-       if (CmiGetXHandler(msg)==_charmHandlerIdx) {isCharm=1; type="Network Charm";}
+        if (CmiGetHandler(msg)==_charmHandlerIdx) {isCharm=1; type="Local Charm";}
+        if (CmiGetXHandler(msg)==_charmHandlerIdx) {isCharm=1; type="Network Charm";}
         sprintf(name,"%s %d: %s (%d)","Message",curObj,type,CmiGetHandler(msg));
         p(name, strlen(name));
-       
-       if (isCharm) 
-       { /* charm message */
+        
+        if (isCharm) 
+        { /* charm message */
           p.comment("charmMsg");
-         p.synchronize(PUP::sync_begin_object);
-         envelope *env=(envelope *)msg;
-         CkUnpackMessage(&env);
-         messages[curObj]=env;
+          p.synchronize(PUP::sync_begin_object);
+          envelope *env=(envelope *)msg;
+          CkUnpackMessage(&env);
+          messages[curObj]=env;
           CpdPupMessage(p, EnvToUsr(env));
           //CkPupMessage(p, &messages[curObj], 0);
-         p.synchronize(PUP::sync_end_object);
-       }
-    }
+          p.synchronize(PUP::sync_end_object);
+        }
+      }
     delete[] messages;
 
   }
@@ -366,14 +384,14 @@ typedef CkHashtableTslow<int,EntryInfo *> CpdBpFuncTable_t;
 
 extern void CpdFreeze(void);
 extern void CpdUnFreeze(void);
-
+extern int  CpdIsFrozen(void);
 
 CpvStaticDeclare(int, _debugMsg);
 CpvStaticDeclare(int, _debugChare);
 
 CpvStaticDeclare(CpdBpFuncTable_t *, breakPointEntryTable);
 
-CpvStaticDeclare(void *, lastBreakPointMsg);
+//CpvStaticDeclare(void *, lastBreakPointMsg);
 CpvStaticDeclare(void *, lastBreakPointObject);
 CpvStaticDeclare(int, lastBreakPointIndex);
 
@@ -390,6 +408,7 @@ void CpdBreakPointInit()
   CpvAccess(lastBreakPointIndex) = 0;
   CpvAccess(_debugMsg) = CkRegisterMsg("debug_msg",0,0,0);
   CpvAccess(_debugChare) = CkRegisterChare("debug_Chare",0);
+  CkRegisterChareInCharm(CpvAccess(_debugChare));
   CpvAccess(breakPointEntryTable) = new CpdBpFuncTable_t(10,0.5,CkHashFunction_int,CkHashCompare_int );
 }
 
@@ -400,15 +419,45 @@ static void _call_freeze_on_break_point(void * msg, void * object)
       //Save breakpoint entry point index. This is retrieved from msg.
       //So that the appropriate EntryInfo can be later retrieved from the hash table 
       //of break point function entries, on continue.
+  
+  // If the counter "skipBreakpoint" is not zero we actually do not freeze and deliver the regular message
+  if (CpvAccess(skipBreakpoint) > 0) {
+    EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(CkMessageToEpIdx(msg));
+    CkAssert(breakPointEntryInfo != NULL);
+    breakPointEntryInfo->call(msg, object);
+    CpvAccess(skipBreakpoint) --;
+  } else {
       CpvAccess(lastBreakPointMsg) = msg;
       CpvAccess(lastBreakPointObject) = object;
       CpvAccess(lastBreakPointIndex) = CkMessageToEpIdx(msg);
       EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(CpvAccess(lastBreakPointIndex));
       CmiPrintf("Break point reached for Function = %s\n", breakPointEntryInfo->name);
       CpdFreeze();
+  }
 }
 
-
+//ccs handler when pressed the "next" command: deliver only a single message without unfreezing
+extern "C"
+void CpdDeliverSingleMessage () {
+  if (!CpdIsFrozen()) return; /* Do something only if we are in freeze mode */
+  if ( (CpvAccess(lastBreakPointMsg) != NULL) && (CpvAccess(lastBreakPointObject) != NULL) ) {
+    EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(CpvAccess(lastBreakPointIndex));
+    if (breakPointEntryInfo != NULL) {
+      breakPointEntryInfo->call(CpvAccess(lastBreakPointMsg), CpvAccess(lastBreakPointObject));
+    }
+    CpvAccess(lastBreakPointMsg) = NULL;
+    CpvAccess(lastBreakPointObject) = NULL;
+  }
+  else {
+    // we were not stopped at a breakpoint, then deliver the first message in the debug queue
+    if (!CdsFifo_Empty(CpvAccess(debugQueue))) {
+      CpvAccess(skipBreakpoint) = 1;
+      char *queuedMsg = (char *)CdsFifo_Dequeue(CpvAccess(debugQueue));
+      CmiHandleMessage(queuedMsg);
+      CpvAccess(skipBreakpoint) = 0;
+    }
+  }
+}
 
 //ccs handler when continue from a break point
 extern "C"
@@ -436,10 +485,15 @@ void CpdSetBreakPoint (char *msg)
     tableSize = _entryTable.size();
     // Replace entry in entry table with _call_freeze_on_break_point
     // retrieve epIdx for entry method
-    for (tableIdx=0; tableIdx < tableSize; tableIdx++)
-    {
-       if (strstr(_entryTable[tableIdx]->name, functionName) != NULL)
-       {
+    //for (tableIdx=0; tableIdx < tableSize; tableIdx++)
+    //{
+       //if (strstr(_entryTable[tableIdx]->name, functionName) != NULL)
+       //{
+    tableIdx = atoi(functionName);
+    if (tableIdx < 0 || tableIdx >= tableSize) {
+      CmiPrintf("[ERROR]Entrypoint was not found for function %s\n", functionName); 
+      return;
+    }
             EntryInfo * breakPointEntryInfo = new EntryInfo(_entryTable[tableIdx]->name, _entryTable[tableIdx]->call, _entryTable[tableIdx]->msgIdx, _entryTable[tableIdx]->chareIdx );
            CmiPrintf("Breakpoint is set for function %s with an epIdx = %ld\n", _entryTable[tableIdx]->name, tableIdx);
            CpvAccess(breakPointEntryTable)->put(tableIdx) = breakPointEntryInfo;  
@@ -447,14 +501,14 @@ void CpdSetBreakPoint (char *msg)
            _entryTable[tableIdx]->call = (CkCallFnPtr)_call_freeze_on_break_point;
            _entryTable[tableIdx]->msgIdx = CpvAccess(_debugMsg); 
            _entryTable[tableIdx]->chareIdx = CpvAccess(_debugChare);
-           break;
-       }
-    }
-    if (tableIdx == tableSize)
-    {
-      CmiPrintf("[ERROR]Entrypoint was not found for function %s\n", functionName); 
-      return;
-    }
+           //break;
+       //}
+    //}
+    //if (tableIdx == tableSize)
+    //{
+    //  CmiPrintf("[ERROR]Entrypoint was not found for function %s\n", functionName); 
+    //  return;
+    //}
 
   }
 
@@ -470,20 +524,28 @@ void CpdRemoveBreakPoint (char *msg)
 {
   char functionName[128];
   sscanf(msg+CmiMsgHeaderSizeBytes, "%s", functionName);
-  void *objPointer;
-  void *keyPointer; 
-  CkHashtableIterator *it = CpvAccess(breakPointEntryTable)->iterator();
-  while(NULL!=(objPointer = it->next(&keyPointer)))
-  {
-    EntryInfo * breakPointEntryInfo = *(EntryInfo **)objPointer;
-    int idx = *(int *)keyPointer;
-    if (strstr(breakPointEntryInfo->name, functionName) != NULL){
+  if (strlen(functionName) > 0) {
+  int idx = atoi(functionName);
+  if (idx < 0 || idx >= _entryTable.size()) {
+    CmiPrintf("[ERROR]Entrypoint was not found for function %s\n", functionName); 
+    return;
+  }
+  //void *objPointer;
+  //void *keyPointer; 
+  //CkHashtableIterator *it = CpvAccess(breakPointEntryTable)->iterator();
+  //while(NULL!=(objPointer = it->next(&keyPointer)))
+  //{
+  //EntryInfo * breakPointEntryInfo = *(EntryInfo **)objPointer;
+  EntryInfo * breakPointEntryInfo = CpvAccess(breakPointEntryTable)->get(idx);
+    //int idx = *(int *)keyPointer;
+    //if (strstr(breakPointEntryInfo->name, functionName) != NULL){
         _entryTable[idx]->name =  breakPointEntryInfo->name;
         _entryTable[idx]->call = (CkCallFnPtr)breakPointEntryInfo->call;
         _entryTable[idx]->msgIdx = breakPointEntryInfo->msgIdx;
         _entryTable[idx]->chareIdx = breakPointEntryInfo->chareIdx;
         CmiPrintf("Breakpoint is removed for function %s with epIdx %ld\n", _entryTable[idx]->name, idx);
-    }
+    //}
+  //}
   }
 }
 
@@ -504,7 +566,11 @@ void CpdRemoveAllBreakPoints ()
   }
 }
 
-
+extern "C" CmiBool isDebugMessage(void *msg) {
+  envelope *env = (envelope*)msg;
+  // Later should use "isDebug" value, but for now just bypass all intrinsic EPs
+  return _entryTable[env->getEpIdx()]->inCharm;
+}
 
 
 
@@ -562,6 +628,7 @@ void CpdCharmInit()
   CcsRegisterHandler("ccs_remove_break_point",(CmiHandler)CpdRemoveBreakPoint);
   CcsRegisterHandler("ccs_remove_all_break_points",(CmiHandler)CpdRemoveAllBreakPoints);
   CcsRegisterHandler("ccs_continue_break_point",(CmiHandler)CpdContinueFromBreakPoint);
+  CcsRegisterHandler("ccs_single_step",(CmiHandler)CpdDeliverSingleMessage);
   CcsRegisterHandler("ccs_debug_quit",(CmiHandler)CpdQuitDebug);
   CcsRegisterHandler("ccs_debug_startgdb",(CmiHandler)CpdStartGdb);
   CpdListRegister(new CpdListAccessor_c("hostinfo",hostInfoLength,0,hostInfo,0));
index 3a76abeaa9e22bd0c4fe3f69a12a50d179b379b3..d554a5d157d252c4f19dcaa2dc7a51c736ef65dd 100644 (file)
@@ -9,6 +9,7 @@
 #  error "debug-charm.h is for C++; use debug-conv.h for C programs"
 #endif
 
+#include "converse.h"
 #include "pup.h"
 
 //These pup functions are useful in CpdLists, as they document the name
index 43f092adaff0f6914bea5a15f27d83c5224741b8..ddd382ca264c8455a7be888322fb039afb6884be 100644 (file)
@@ -762,9 +762,11 @@ void _initCharm(int unused_argc, char **argv)
                _parseCommandLineOpts(argv);
                _registerInit();
                CkRegisterMsg("System", 0, 0, sizeof(int));
-               CkRegisterChare("null", 0);
+               CkRegisterChareInCharm(CkRegisterChare("null", 0));
                CkIndex_Chare::__idx=CkRegisterChare("Chare", sizeof(Chare));
+               CkRegisterChareInCharm(CkIndex_Chare::__idx);
                CkIndex_Group::__idx=CkRegisterChare("Group", sizeof(Group));
+        CkRegisterChareInCharm(CkIndex_Group::__idx);
                CkRegisterEp("null", (CkCallFnPtr)_nullFn, 0, 0, 0+CK_EP_INTRINSIC);
                
                /**
index 103aad7e7a0ef2a3f6707406f1e3cff75e39fea3..8958cb8ea05ee7747001e36a1d49c5043b6acbeb 100644 (file)
@@ -135,18 +135,22 @@ static void traceCommonInit(char **argv)
 #endif
     _threadMsg = CkRegisterMsg("dummy_thread_msg", 0, 0, 0);
     _threadChare = CkRegisterChare("dummy_thread_chare", 0);
+    CkRegisterChareInCharm(_threadChare);
     _threadEP = CkRegisterEp("dummy_thread_ep", 0, _threadMsg,_threadChare, 0+CK_EP_INTRINSIC);
 
     _packMsg = CkRegisterMsg("dummy_pack_msg", 0, 0, 0);
     _packChare = CkRegisterChare("dummy_pack_chare", 0);
+    CkRegisterChareInCharm(_packChare);
     _packEP = CkRegisterEp("dummy_pack_ep", 0, _packMsg,_packChare, 0+CK_EP_INTRINSIC);
 
     _unpackMsg = CkRegisterMsg("dummy_unpack_msg", 0, 0, 0);
     _unpackChare = CkRegisterChare("dummy_unpack_chare", 0);
+    CkRegisterChareInCharm(_unpackChare);
     _unpackEP = CkRegisterEp("dummy_unpack_ep", 0, _unpackMsg,_unpackChare, 0+CK_EP_INTRINSIC);
 
     _dummyMsg = CkRegisterMsg("dummy_msg", 0, 0, 0);
     _dummyChare = CkRegisterChare("dummy_chare", 0);
+    CkRegisterChareInCharm(_dummyChare);
     _dummyEP = CkRegisterEp("dummy_ep", 0, _dummyMsg,_dummyChare, 0+CK_EP_INTRINSIC);
   }
 }
index f1e0402a858b0354eae0c14f91e882daa942490c..d870990bca9df83f5cbeba18b9c1acf13de56a9a 100644 (file)
@@ -5,6 +5,8 @@
 #define DEBUGF(x) // CmiPrintf x
 
 CkpvStaticDeclare(TraceMemory*, _trace);
+extern "C" void memory_trace_all_existing_mallocs();
+extern "C" int get_memory_allocated_user_total();
 
 /**
   For each TraceFoo module, _createTraceFoo() must be defined.
@@ -16,17 +18,24 @@ void _createTracememory(char **argv)
   CkpvInitialize(TraceMemory*, _trace);
   CkpvAccess(_trace) = new TraceMemory(argv);
   CkpvAccess(_traces)->addTrace(CkpvAccess(_trace));
+  /* Since we started after the beginning of the program, we missed a bunch of
+   * allocations. We cannot record what was allocated and then deleted, but we
+   * can still record all the memory that is still allocated.
+   */
 }
 
 MemEntry::MemEntry() : type(0), where(0), size(0), stackSize(0) { }
 
 void MemEntry::write(FILE *fp) {
-  fprintf(fp, "%d %p", type, where);
+  if (type == BEGIN_TRACE) {
+    fprintf(fp, "%d %d\n", type, size);
+    return;
+  }
+  fprintf(fp, "%d %p %d", type, where, size);
   if (type == MEMORY_MALLOC) {
-    fprintf(fp, " %d", size);
     fprintf(fp, " %d", stackSize);
     void **stack = (void**)(this+1);
-    for (int i=0; i<stackSize; ++i) {
+    for (int i=stackSize-1; i>=0; --i) {
       fprintf(fp, " %p", stack[i]);
     }
   }
@@ -90,6 +99,13 @@ void TraceMemory::traceClose() {
   flush();
 }
 
+void TraceMemory::traceBegin() {
+  int increment = sizeof(MemEntry);
+  checkFlush(increment);
+  ((MemEntry*)&logBuffer[usedBuffer])->set(BEGIN_TRACE, 0, get_memory_allocated_user_total());
+  usedBuffer += increment;
+}
+
 void TraceMemory::malloc(void *where, int size, void **stack, int stackSize) {
   if (!traceDisabled) {
     int increment = sizeof(MemEntry) + (recordStack ? stackSize*sizeof(void*) : 0);
@@ -101,11 +117,11 @@ void TraceMemory::malloc(void *where, int size, void **stack, int stackSize) {
   }
 }
 
-void TraceMemory::free(void *where) {
+void TraceMemory::free(void *where, int size) {
   if (!traceDisabled) {
     int increment = sizeof(MemEntry);
     checkFlush(increment);
-    ((MemEntry*)&logBuffer[usedBuffer])->set(MEMORY_FREE, where);
+    ((MemEntry*)&logBuffer[usedBuffer])->set(MEMORY_FREE, where, size);
     usedBuffer += increment;
     //CmiPrintf("[%d] TraceMemory::free    %d  (%p)\n",CmiMyPe(),usedBuffer,where);
   }
index 9f4cb803ecd002eeb807673295bd22971f0085e6..3490c4093d368c7a96edf8362b29db7c19a40f43 100644 (file)
@@ -19,7 +19,7 @@ class MemEntry {
  public:  
   MemEntry();
   void write(FILE *fp);
-  void set(int t, void *w, int s=0) {
+  void set(int t, void *w, int s) {
     type = t;
     where = w;
     size = s;
@@ -49,9 +49,10 @@ class TraceMemory : public Trace {
  public:
   TraceMemory(char **argv);
   
+  void traceBegin();
   void traceClose();
   void malloc(void *where, int size, void **stack, int stackSize);
-  void free(void *where);
+  void free(void *where, int size);
 };
 
 #endif
index 411c2086b30f1190e9aaa0dbba9ca722ff7fd3e5..329ee419c7e53d3b32c37327ff32e0bf37500c07 100644 (file)
@@ -137,7 +137,7 @@ class Trace {
 
     /* Memory tracing */
     virtual void malloc(void *where, int size, void **stack, int stackSize){}
-    virtual void free(void *where){}
+    virtual void free(void *where, int size){}
 
     /* for implementing thread listeners */
     virtual void traceAddThreadListeners(CthThread tid, envelope *e) {}
@@ -236,7 +236,7 @@ public:
 
     /* Memory tracing */
     inline void malloc(void *where, int size, void **stack, int stackSize){ ALLDO(malloc(where,size,stack,stackSize)); }
-    inline void free(void *where){ ALLDO(free(where)); }
+    inline void free(void *where, int size){ ALLDO(free(where, size)); }
 
     /* calls for thread listener registration for each trace module */
     inline void traceAddThreadListeners(CthThread tid, envelope *e) {
@@ -283,7 +283,7 @@ extern "C" {
 
 /* Memory tracing */
 #define _TRACE_MALLOC(where, size, stack, stackSize) _TRACE_ONLY(CkpvAccess(_traces)->malloc(where,size,stack,stackSize))
-#define _TRACE_FREE(where) _TRACE_ONLY(CkpvAccess(_traces)->free(where))
+#define _TRACE_FREE(where, size) _TRACE_ONLY(CkpvAccess(_traces)->free(where, size))
 
 
 #include "trace-bluegene.h"
index 8ee481faa8d1a9fd3b31755d590112a6791bcee6..dfadbb9912fa970049a00960b203c993186ea360 100644 (file)
@@ -9,8 +9,8 @@ extern "C" {
     _TRACE_MALLOC(where, size, stack, stackSize);
   }
 
-  void traceFree_c(void *where) {
-    _TRACE_FREE(where);
+  void traceFree_c(void *where, int size) {
+    _TRACE_FREE(where, size);
   }
 
 }
index de3606d82b8096a173fe52e6761610706ca6b0de..6482ade0e804141f02af8c532095eeec5461aa01 100644 (file)
@@ -6,7 +6,7 @@ extern "C" {
 #endif
 
   extern void traceMalloc_c(void *where, int size, void **stack, int stackSize);
-  extern void traceFree_c(void *where);
+  extern void traceFree_c(void *where, int size);
 
 #ifdef __cplusplus
 }
index 3d6c04982b483a68a1200b68a751dfefbe858541..4d52f62caf8883498037a25e080080993412d868 100644 (file)
@@ -164,6 +164,8 @@ static void CcsHandleRequest(CcsImplHeader *hdr,const char *reqData)
   if (fn==NULL) {
     CmiPrintf("CCS: Unknown CCS handler name '%s' requested. Ignoring...\n",
              hdr->handler);
+    CpvAccess(ccsReq)=hdr;
+    CcsSendReply(0,NULL); /*Send an empty reply to the possibly waiting client*/
     return;
  /*   CmiAbort("CCS: Unknown CCS handler name.\n");*/
   }
index eb59028bd91b4962f882e0c30839ab87148b0bbe..b4dd1f5bf8d23b4ac429088ba9fa570e263300da 100644 (file)
@@ -627,7 +627,6 @@ int CmiRegisterHandlerEx(CmiHandlerEx h,void *userPtr)
   return Count;
 }
 
-
 #if CMI_LOCAL_GLOBAL_AVAILABLE
 int CmiRegisterHandlerLocal(h)
 CmiHandler h;
@@ -1761,6 +1760,11 @@ static void * (*_reduce_mergeFn)(void*,void**,int);
 static void (*_reduce_pupFn)(void*,void*);
 static void (*_reduce_deleteFn)(void*);
 
+CpvStaticDeclare(CmiUInt2, _reduce_seqID);
+
+int CmiGetReductionHandler() { return CpvAccess(CmiReductionMessageHandler); }
+CmiHandler CmiGetReductionDestination() { return _reduce_destination; }
+
 CmiReductionsInit() {
   CpvInitialize(int, CmiReductionMessageHandler);
   CpvAccess(CmiReductionMessageHandler) = CmiRegisterHandler((CmiHandler)CmiHandleReductionMessage);
@@ -1773,6 +1777,14 @@ CmiReductionsInit() {
   CpvAccess(_reduce_num_children) = 0;
   CpvAccess(_reduce_received) = 0;
   CpvAccess(_reduce_msg_list) = (char**)malloc(CmiNumSpanTreeChildren(CmiMyPe())*sizeof(void*));
+
+  CpvInitialize(CmiUInt2, _reduce_seqID);
+  CpvAccess(_reduce_seqID) = 0x8000;
+}
+
+int CmiReduceNextID() {
+  if (CpvAccess(_reduce_seqID) == 0xffff) CpvAccess(_reduce_seqID) = 0x8000;
+  return ++CpvAccess(_reduce_seqID);
 }
 
 void CmiSendReduce() {
@@ -1837,7 +1849,7 @@ void CmiReduceStruct(void *data, void (*pupFn)(void*,void*),
   /*else CmiPrintf("CmiReduceStruct(%d): %d - %d\n",CmiMyPe(),CpvAccess(_reduce_received),CpvAccess(_reduce_num_children));*/
 }
 
-void CmiNodeReduce(void *data, int size, void * (*mergeFn)(void*,void**,int)) {
+void CmiNodeReduce(void *data, int size, void * (*mergeFn)(void*,void**,int), int redID, int numChildren, int parent) {
   CmiAssert(CmiRankOf(CmiMyPe()) == 0);
   CpvAccess(_reduce_data) = data;
   CpvAccess(_reduce_data_size) = size;
@@ -1848,6 +1860,17 @@ void CmiNodeReduce(void *data, int size, void * (*mergeFn)(void*,void**,int)) {
   CpvAccess(_reduce_num_children) = CmiNumNodeSpanTreeChildren(CmiMyNode());
   if (CpvAccess(_reduce_received) == CpvAccess(_reduce_num_children)) CmiSendReduce();
 }
+//void CmiNodeReduce(void *data, int size, void * (*mergeFn)(void*,void**,int), int redID) {
+//  CmiNodeReduce(data, size, mergeFn, redID, CmiNumNodeSpanTreeChildren(CmiMyNode()),
+//      CmiNodeFirst(CmiNodeSpanTreeParent(CmiMyNode())));
+//}
+//void CmiNodeReduce(void *data, int size, void * (*mergeFn)(void*,void**,int), int numChildren, int parent) {
+//  CmiNodeReduce(data, size, mergeFn, CmiReduceNextID(), numChildren, parent);
+//}
+//void CmiNodeReduce(void *data, int size, void * (*mergeFn)(void*,void**,int)) {
+//  CmiNodeReduce(data, size, mergeFn, CmiReduceNextID(), CmiNumNodeSpanTreeChildren(CmiMyNode()),
+//      CmiNodeFirst(CmiNodeSpanTreeParent(CmiMyNode())));
+//}
 
 void CmiNodeReduceStruct(void *data, void (*pupFn)(void*,void*),
                          void * (*mergeFn)(void*,void**,int), CmiHandler dest,
index b94c1c9782679d1b5afd0cc2afa5843cec098686..43554fd1c8be8a801b8862aad0e4c331c8cad4e2 100644 (file)
@@ -79,9 +79,12 @@ extern "C" {
 /* Global variables used by charmdebug to maintain information */
 #ifndef CMK_OPTIMIZE
 extern int memory_status_info;
+extern int memory_chare_id;
 #define setMemoryStatus(p) memory_status_info = p;
+void setMemoryChareID(void *p);
 #else
 #define setMemoryStatus(p) /* empty */
+#define setMemoryChareID(p) /* empty */
 #endif
 
 /******************************************************************************
@@ -871,15 +874,31 @@ void          CmiSyncMulticastFn(CmiGroup, int, char*);
 CmiCommHandle CmiAsyncMulticastFn(CmiGroup, int, char*);
 void          CmiFreeMulticastFn(CmiGroup, int, char*);
 
+typedef struct {
+  void *localMessage;
+  void *remoteMessages;
+  int numRemoteReceived;
+  int numChildren;
+  int parent;
+  struct {
+    CmiHandler destination;
+    void * (*mergeFn)(void*,void**,int);
+    void (*pupFn)(void*,void*);
+    void (*deleteFn)(void*);
+  } ops;
+} CmiReduction;
+
 void CmiReduce(void *msg, int size, void * (*mergeFn)(void*,void**,int));
 void CmiReduceStruct(void *data, void (*pupFn)(void*,void*),
                      void * (*mergeFn)(void*,void**,int), CmiHandler dest,
                      void (*deleteFn)(void*));
-void CmiNodeReduce(void *msg, int size, void * (*mergeFn)(void*,void**,int));
+void CmiNodeReduce(void *msg, int size, void * (*mergeFn)(void*,void**,int), int, int, int);
 void CmiNodeReduceStruct(void *data, void (*pupFn)(void*,void*),
                          void * (*mergeFn)(void*,void**,int), CmiHandler dest,
                          void (*deleteFn)(void*));
 void CmiHandleReductionMessage(void *msg);
+int CmiGetReductionHandler();
+CmiHandler CmiGetReductionDestination();
 
 /* If the second parameter (the number of chunks to send) is negative, then
  * every message will be started aligned with 8 bytes, and a message header will
index 475173a2a597463114a02b98b5ace0c99d6ff967..8e45ed19266c0a07e601faea3b668e9cfcfd5d59 100644 (file)
@@ -16,6 +16,8 @@ CpvStaticDeclare(int, freezeModeFlag);
 CpvStaticDeclare(int, continueFlag);
 CpvStaticDeclare(int, stepFlag);
 CpvDeclare(void *, debugQueue);
+int _debugHandlerIdx;
+CpvDeclare(int, skipBreakpoint); /* This is a counter of how many breakpoints we should skip */
 
 /***************************************************
   The CCS interface to the debugger
@@ -29,6 +31,7 @@ void (*CpdDebug_pupAllocationPoint)(pup_er p, void *data);
 void (*CpdDebug_deleteAllocationPoint)(void *ptr);
 void * (*CpdDebug_MergeAllocationTree)(void *data, void **remoteData, int numRemote);
 CpvDeclare(int, CpdDebugCallAllocationTree_Index);
+CpvStaticDeclare(CcsDelayedReply, allocationTreeDelayedReply);
 
 static void CpdDebugReturnAllocationTree(void *tree) {
   pup_er sizer = pup_new_sizer();
@@ -42,7 +45,7 @@ static void CpdDebugReturnAllocationTree(void *tree) {
   /*CmiPrintf("size=%d tree:",pup_size(sizer));
   for (i=0;i<100;++i) CmiPrintf(" %02x",((unsigned char*)buf)[i]);
   CmiPrintf("\n");*/
-  CcsSendReply(pup_size(sizer),buf);
+  CcsSendDelayedReply(CpvAccess(allocationTreeDelayedReply), pup_size(sizer),buf);
   pup_destroy(sizer);
   pup_destroy(packer);
   free(buf);
@@ -54,9 +57,12 @@ static void CpdDebugCallAllocationTree(char *msg)
   int forPE;
   void *tree;
   sscanf(msg+CmiMsgHeaderSizeBytes, "%d", &forPE);
+  if (CmiMyPe() == forPE) CpvAccess(allocationTreeDelayedReply) = CcsDelayReply();
   if (forPE == -1 && CmiMyPe()==0) {
-    CmiSetHandler(msg, CpvAccess(CpdDebugCallAllocationTree_Index));
-    CmiSyncBroadcast(CmiMsgHeaderSizeBytes+sizeof(int), msg);
+    CpvAccess(allocationTreeDelayedReply) = CcsDelayReply();
+    CmiSetXHandler(msg, CpvAccess(CpdDebugCallAllocationTree_Index));
+    CmiSetHandler(msg, _debugHandlerIdx);
+    CmiSyncBroadcast(CmiMsgHeaderSizeBytes+strlen(msg+CmiMsgHeaderSizeBytes)+1, msg);
   }
   tree = CpdDebugGetAllocationTree(&numNodes);
   if (forPE == CmiMyPe()) CpdDebugReturnAllocationTree(tree);
@@ -117,11 +123,29 @@ void CpdUnFreeze(void)
   CpvAccess(freezeModeFlag) = 0;
 }
 
+int CpdIsFrozen(void) {
+  return CpvAccess(freezeModeFlag);
+}
+
+/* Deliver a single message in the queue while not unfreezing the program */
+void CpdNext(void) {
+  
+}
+
+/* This converse handler is used by the debugger itself, to send messages
+ * even when the scheduler is in freeze mode.
+ */
+void handleDebugMessage(void *msg) {
+  CmiSetHandler(msg, CmiGetXHandler(msg));
+  CmiHandleMessage(msg);
+}
+
 /* Special scheduler-type loop only executed while in
 freeze mode-- only executes CCS requests.
 */
 void CcsServerCheck(void);
 extern int _isCcsHandlerIdx(int idx);
+extern int _charmHandlerIdx;
 
 void CpdFreezeModeScheduler(void)
 {
@@ -140,13 +164,22 @@ void CpdFreezeModeScheduler(void)
 
       if (msg!=NULL) {
          int hIdx=CmiGetHandler(msg);
+         /*
          if(_isCcsHandlerIdx(hIdx))
-         /*A CCS request-- handle it immediately*/
+         / *A CCS request-- handle it immediately* /
           {
            CmiHandleMessage(msg);
           }
+         else if (hIdx == _debugHandlerIdx ||
+                 (hIdx == CmiGetReductionHandler() && CmiGetReductionDestination() == CpdDebugReturnAllocationTree)) {
+           / * Debug messages should be handled immediately * /
+           CmiHandleMessage(msg);
+         } else */
+         if (hIdx != _charmHandlerIdx || isDebugMessage(msg)) {
+           CmiHandleMessage(msg);
+         }
          else
-         /*An ordinary message-- queue it up*/
+         /*An ordinary charm++ message-- queue it up*/
            CdsFifo_Enqueue(debugQ, msg);
       } else CmiNotifyIdle();
     }
@@ -174,6 +207,7 @@ void CpdInit(void)
   CpvInitialize(int, CpdDebugCallAllocationTree_Index);
   CpvAccess(CpdDebugCallAllocationTree_Index) = CmiRegisterHandler((CmiHandler)CpdDebugCallAllocationTree);
   
+  _debugHandlerIdx = CmiRegisterHandler((CmiHandler)handleDebugMessage);
 #if 0
   CpdInitializeObjectTable();
   CpdInitializeHandlerArray();
index 0bff5842b8cb478b3afb840e0939c40a24174139..6fd0280f1b94559763866625ee15f987dc27f9ab 100644 (file)
@@ -19,6 +19,7 @@ extern void * (*CpdDebug_MergeAllocationTree)(void *data, void **remoteData, int
 void CpdInit(void); 
 void CpdFreeze(void);  
 void CpdUnFreeze(void);
+int  CpdIsFrozen(void);
 void CpdFreezeModeScheduler(void);
 void CpdStartGdb(void);
 void Cpd_CmiHandleMessage(void *msg);
index ebff898bc3477ab4edbdb20eb00c578222e42ea1..ed3423f2611b8b8caf4d869270284ba99711c397 100644 (file)
@@ -24,6 +24,9 @@
 typedef struct _Slot Slot;
 typedef struct _SlotStack SlotStack;
 
+int nextChareID;
+int memory_chare_id;
+
 /**
  * Struct Slot contains all of the information about a malloc buffer except
  * for the contents of its memory.
@@ -51,7 +54,7 @@ struct _Slot {
 #define SLOTMAGIC_FREED      0xDEADBEEF
   int magic;
 
-  int pad;
+  int chareID;
   /* Controls the number of stack frames to print out. Should be always odd, so
      the total size of this struct becomes multiple of 8 bytes everywhere */
 //#define STACK_LEN 15
@@ -97,6 +100,9 @@ static void printSlot(Slot *s) {
 Slot slot_first_storage = {&slot_first_storage, &slot_first_storage};
 Slot *slot_first = &slot_first_storage;
 
+int memory_allocated_user_total;
+int get_memory_allocated_user_total() {return memory_allocated_user_total;}
+
 /********* Cpd routines for pupping data to the debugger *********/
 
 int cpd_memory_length(void *lenParam) {
@@ -126,6 +132,8 @@ void cpd_memory_single_pup(Slot* list, pup_er p) {
     pup_comment(p, "flags");
     flags = cur->magic & FLAGS_MASK;
     pup_int(p, &flags);
+    pup_comment(p, "chare");
+    pup_int(p, &cur->chareID);
     pup_comment(p, "stack");
     //for (i=0; i<STACK_LEN; ++i) {
     //  if (cur->from[i] <= 0) break;
@@ -430,6 +438,12 @@ void pupAllocationPointSingle(pup_er p, AllocationPoint *node, int *numChildren)
   pup_int(p, &node->size);
   pup_int(p, &node->count);
   pup_char(p, &node->flags);
+  if (pup_isUnpacking(p)) {
+    node->parent = NULL;
+    node->firstChild = NULL;
+    node->sibling = NULL;
+    node->next = NULL;
+  }
   *numChildren = 0;
   AllocationPoint *child;
   for (child = node->firstChild; child != NULL; child = child->sibling) (*numChildren) ++;
@@ -556,13 +570,51 @@ AllocationPoint * CreateAllocationTree(int *nodesCount) {
   return root;
 }
 
-void MergeAllocationTreeSingle(AllocationPoint *node, AllocationPoint *remote) {
-  
+void MergeAllocationTreeSingle(AllocationPoint *node, AllocationPoint *remote, int numChildren, pup_er p) {
+  AllocationPoint child;
+  int numChildChildren;
+  int i;
+  //pupAllocationPointSingle(p, &remote, &numChildren);
+  /* Update the node with the information coming from remote */
+  node->size += remote->size;
+  node->count += remote->count;
+  node->flags |= remote->flags;
+  /* Recursively merge the children */
+  for (i=0; i<numChildren; ++i) {
+    AllocationPoint *localChild;
+    pupAllocationPointSingle(p, &child, &numChildChildren);
+    /* Find the child in the local tree */
+    for (localChild = node->firstChild; localChild != NULL; localChild = localChild->sibling) {
+      if (localChild->key == child.key) {
+        break;
+      }
+    }
+    if (localChild == NULL) {
+      /* This child did not exist locally, allocate it */
+      localChild = (AllocationPoint*) mm_malloc(sizeof(AllocationPoint));
+      localChild->key = child.key;
+      localChild->flags = 0;
+      localChild->count = 0;
+      localChild->size = 0;
+      localChild->firstChild = NULL;
+      localChild->next = NULL;
+      localChild->parent = node;
+      localChild->sibling = node->firstChild;
+      node->firstChild = localChild;
+    }
+    MergeAllocationTreeSingle(localChild, &child, numChildChildren, p);
+  }
 }
 
 void * MergeAllocationTree(void *data, void **remoteData, int numRemote) {
   int i;
-  for (i=0; i<numRemote; ++i) MergeAllocationTreeSingle((AllocationPoint*)data, (AllocationPoint*)remoteData[i]);
+  for (i=0; i<numRemote; ++i) {
+    pup_er p = pup_new_fromMem(remoteData[i]);
+    AllocationPoint root;
+    int numChildren;
+    pupAllocationPointSingle(p, &root, &numChildren);
+    MergeAllocationTreeSingle((AllocationPoint*)data, &root, numChildren, p);
+  }
   return data;
 }
 
@@ -639,6 +691,7 @@ static void *setSlot(Slot *s,int userSize) {
   /* Set the last 4 bits of magic to classify the memory together with the magic */
   s->magic=SLOTMAGIC + (memory_status_info>0? USER_TYPE : SYSTEM_TYPE);
   //if (memory_status_info>0) printf("user allocation\n");
+  s->chareID = memory_chare_id;
   s->userSize=userSize;
   s->extraStack=(SlotStack *)0;
 
@@ -707,6 +760,8 @@ static void meta_init(char **argv) {
   CpdDebug_pupAllocationPoint = pupAllocationPoint;
   CpdDebug_deleteAllocationPoint = deleteAllocationPoint;
   CpdDebug_MergeAllocationTree = MergeAllocationTree;
+  memory_allocated_user_total = 0;
+  nextChareID = 1;
 }
 
 static void *meta_malloc(size_t size) {
@@ -714,13 +769,17 @@ static void *meta_malloc(size_t size) {
   Slot *s=(Slot *)mm_malloc(sizeof(Slot)+size+numStackFrames*sizeof(void*));
   char *user = (char*)s;
   if (s!=NULL) user = setSlot(s,size);
+  memory_allocated_user_total += size;
   traceMalloc_c(user, size, s->from, s->stackLen);
   return user;
 }
 
 static void meta_free(void *mem) {
   Slot *s;
-  traceFree_c(mem);
+  int memSize = 0;
+  if (mem!=NULL) memSize = (((Slot*)mem)-1)->userSize;
+  memory_allocated_user_total -= memSize;
+  traceFree_c(mem, memSize);
   if (mem==NULL) return; /*Legal, but misleading*/
 
   s=((Slot *)mem)-1;
@@ -779,6 +838,7 @@ static void *meta_memalign(size_t align, size_t size) {
   s->extraStack = (SlotStack *)alloc; /* use the extra space as stack */
   s->extraStack->protectedMemory = NULL;
   s->extraStack->protectedMemoryLength = 0;
+  memory_allocated_user_total += size;
   traceMalloc_c(user, size, s->from, s->stackLen);
   return user;  
 }
@@ -802,6 +862,8 @@ void setProtection(char* mem, char *ptr, int len, int flag) {
 void setMemoryTypeChare(void *ptr) {
   Slot *sl = UserToSlot(ptr);
   sl->magic = (sl->magic & ~FLAGS_MASK) | CHARE_TYPE;
+  sl->chareID = nextChareID;
+  nextChareID ++;
 }
 
 /* The input parameter is the pointer to the envelope, after the CmiChunkHeader */
@@ -812,3 +874,8 @@ void setMemoryTypeMessage(void *ptr) {
     sl->magic = (sl->magic & ~FLAGS_MASK) | MESSAGE_TYPE;
   }
 }
+
+void setMemoryChareID(void *ptr) {
+  if (ptr == NULL || ptr == 0) memory_chare_id = 0;
+  else memory_chare_id = UserToSlot(ptr)->chareID;
+}
index fae1930d73db17d8525f70076e76b6e95277a67b..f534f79172d26bb7e76aac8de4c4708fb8059336 100644 (file)
@@ -91,6 +91,7 @@ void CmiOutOfMemory(int nBytes)
 /* Global variables keeping track of the status of the system (mostly used by charmdebug) */
 #ifndef CMK_OPTIMIZE
 int memory_status_info=0;
+int memory_chare_id=0;
 #endif
 
 #if CMK_MEMORY_BUILD_OS
@@ -399,4 +400,9 @@ void setProtection(char *mem, char *ptr, int len, int flag) { }
 /* Routines used to specify how the memory will the used */
 void setMemoryTypeChare(void *ptr) { }
 void setMemoryTypeMessage(void *ptr) { }
+
+int get_memory_allocated_user_total() { return 0; }
+#ifndef CMK_OPTIMIZE
+void setMemoryChareID(void *ptr) { }
+#endif
 #endif
index 253d1d5bb3dd688df29644b8e473154afb03d15e..f2a76a9fb3cce61b52270e1124241e406c2850e4 100644 (file)
@@ -1,17 +1,27 @@
 CDIR=../../../..
 OPTS=-g -Wall
 CHARMC=$(CDIR)/bin/charmc $(OPTS)
+CHARMXI=$(CHARMC) -intrinsic
 
-HEADERS=PythonCCS.h PythonCCS-client.h PythonCCS.decl.h
-HEADDEP=$(HEADERS) PythonCCS.def.h
+HEADERS=PythonCCS.h PythonCCS-client.h PythonCCS.decl.h pythonIncludes.h
+HEADDEP=$(HEADERS) PythonCCS.def.h charmdebug_python.def.h
 OBJS=PythonCCS.o PythonCCS-client.o
+OBJS_DEBUG=charmdebug-python.o
 DEST=$(CDIR)/lib/libmodulePythonCCS.a
+DEST_DEBUG=$(CDIR)/lib/libmodulecharmdebug_python.a
 
-all: $(DEST) headers
+all:
+       -(CHARMINC=../../../../include;. $$CHARMINC/conv-config.sh; \
+       if test "$$CMK_BUILD_PYTHON" != ""; then ($(MAKE) conditional OPTS='$(OPTS)' || exit 1); fi)
+
+conditional: $(DEST) $(DEST_DEBUG) headers
 
 $(DEST): $(OBJS)
        $(CHARMC) $(OBJS) -o $@
 
+$(DEST_DEBUG): $(OBJS_DEBUG)
+       $(CHARMC) $(OBJS_DEBUG) -o $@
+
 headers: $(HEADERS)
        cp $(HEADERS) $(CDIR)/include/
        touch headers
@@ -23,7 +33,21 @@ PythonCCS-client.o: PythonCCS-client.C $(HEADDEP)
        $(CHARMC) -c $(FLAGS) PythonCCS-client.C
 
 PythonCCS.decl.h PythonCCS.def.h: PythonCCS.ci
-       $(CHARMC) PythonCCS.ci
+       $(CHARMXI) PythonCCS.ci
+
+charmdebug-python.o: charmdebug-python.C $(HEADDEP)
+       $(CHARMC) -c $(FLAGS) -I. charmdebug-python.C
+
+charmdebug_python.decl.h charmdebug_python.def.h: charmdebug-python.ci
+       $(CHARMXI) charmdebug-python.ci
+
+pythonIncludes.h:
+       (CHARMINC=../../../../include;. $$CHARMINC/conv-config.sh; \
+       echo "#include \"python$$CMK_BUILD_PYTHON/Python.h\"\n"\
+       "#include \"python$$CMK_BUILD_PYTHON/compile.h\"\n"\
+       "#include \"python$$CMK_BUILD_PYTHON/eval.h\"\n"\
+       "#include \"python$$CMK_BUILD_PYTHON/node.h\"" > pythonIncludes.h \
+       ) 
 
 clean:
-       rm -rf *.a *~ *.def.h *.decl.h *.o SunWS_cache $(DEST) headers
+       rm -rf *.a *~ *.def.h *.decl.h *.o SunWS_cache $(DEST) $(DEST_DEBUG) pythonIncludes.h headers
index e1133f0a8f384a4adc7b528e822507dfd296536c..32351b9b4dd5d4a1366f0a497bd8c638fae9e426 100644 (file)
@@ -1,10 +1,12 @@
 #include "PythonCCS.h"
 
-CsvDeclare(CmiNodeLock, pyLock);
-CsvDeclare(PythonTable *, pyWorkers);
-CsvDeclare(CmiUInt4, pyNumber);
+//CsvDeclare(CmiNodeLock, pyLock);
+//CsvDeclare(PythonTable *, pyWorkers);
+//CsvDeclare(CmiUInt4, pyNumber);
 CtvDeclare(PyObject *, pythonReturnValue);
 
+CProxy_PythonCCS pythonCcsProxy;
+
 // One-time per-processor setup routine
 // main interface for python to access common charm methods
 static PyObject *CkPy_printstr(PyObject *self, PyObject *args) {
@@ -14,33 +16,36 @@ static PyObject *CkPy_printstr(PyObject *self, PyObject *args) {
   Py_INCREF(Py_None);return Py_None; //Return-nothing idiom
 }
 
-static inline void Ck_printclient(CmiUInt4 ref, char* str) {
-    CmiLock(CsvAccess(pyLock));
+static inline void Ck_printclient(PythonObject *object, CmiUInt4 ref, char* str) {
+  //  CmiLock(CsvAccess(pyLock));
+  PythonStruct &worker = object->pyWorkers[ref];
   //PythonObject *pyWorker = ((*CsvAccess(pyWorkers))[pyReference]).object;
-  if (((*CsvAccess(pyWorkers))[ref]).clientReady > 0) {
+  //if (((*CsvAccess(pyWorkers))[ref]).clientReady > 0) {
+  if (worker.clientReady > 0) {
     // return the string to the client
     // since there is a client waiting, it means there must not be
     // pending strings to be returned ("printed" is empty)
     //CkPrintf("printing data to the client\n");
-    CcsDelayedReply client = ((*CsvAccess(pyWorkers))[ref]).client;
-    CcsSendDelayedReply(client, strlen(str), str);
-    ((*CsvAccess(pyWorkers))[ref]).printed.erase();
-    ((*CsvAccess(pyWorkers))[ref]).clientReady = 0;
+    CcsSendDelayedReply(worker.client, strlen(str), str);
+    worker.printed.erase();
+    worker.clientReady = 0;
   } else {
     // add the string to those in list to be returned if it is keepPrint
-    if (((*CsvAccess(pyWorkers))[ref]).isKeepPrint) {
-      ((*CsvAccess(pyWorkers))[ref]).printed += std::string(str);
+    if (worker.isKeepPrint) {
+      worker.printed += std::string(str);
     }
     // else just drop the line
   }
-  CmiUnlock(CsvAccess(pyLock));
+  //CmiUnlock(CsvAccess(pyLock));
 }
 
 static PyObject *CkPy_print(PyObject *self, PyObject *args) {
   char *stringToPrint;
   if (!PyArg_ParseTuple(args, "s:printclient", &stringToPrint)) return NULL;
-  CmiUInt4 pyReference = PyInt_AsLong(PyDict_GetItemString(PyModule_GetDict(PyImport_AddModule("__main__")),"__charmNumber__"));
-  Ck_printclient(pyReference, stringToPrint);
+  PyObject *dict = PyModule_GetDict(PyImport_AddModule("__main__"));
+  CmiUInt4 pyReference = PyInt_AsLong(PyDict_GetItemString(dict,"__charmNumber__"));
+  PythonObject *object = (PythonObject*)PyLong_AsVoidPtr(PyDict_GetItemString(dict,"__charmObject__"));
+  Ck_printclient(object, pyReference, stringToPrint);
   Py_INCREF(Py_None);return Py_None; //Return-nothing idiom
 }
 
@@ -56,15 +61,17 @@ static PyObject *CkPy_numpes(PyObject *self, PyObject *args) {
 
 static PyObject *CkPy_myindex(PyObject *self, PyObject *args) {
   if (!PyArg_ParseTuple(args, ":myindex")) return NULL;
-  CmiUInt4 pyReference = PyInt_AsLong(PyDict_GetItemString(PyModule_GetDict(PyImport_AddModule("__main__")),"__charmNumber__"));
-  CmiLock(CsvAccess(pyLock));
-  ArrayElement1D *pyArray1 = dynamic_cast<ArrayElement1D*>(((*CsvAccess(pyWorkers))[pyReference]).object);
-  ArrayElement2D *pyArray2 = dynamic_cast<ArrayElement2D*>(((*CsvAccess(pyWorkers))[pyReference]).object);
-  ArrayElement3D *pyArray3 = dynamic_cast<ArrayElement3D*>(((*CsvAccess(pyWorkers))[pyReference]).object);
-  ArrayElement4D *pyArray4 = dynamic_cast<ArrayElement4D*>(((*CsvAccess(pyWorkers))[pyReference]).object);
-  ArrayElement5D *pyArray5 = dynamic_cast<ArrayElement5D*>(((*CsvAccess(pyWorkers))[pyReference]).object);
-  ArrayElement6D *pyArray6 = dynamic_cast<ArrayElement6D*>(((*CsvAccess(pyWorkers))[pyReference]).object);
-  CmiUnlock(CsvAccess(pyLock));
+  PyObject *dict = PyModule_GetDict(PyImport_AddModule("__main__"));
+  CmiUInt4 pyReference = PyInt_AsLong(PyDict_GetItemString(dict,"__charmNumber__"));
+  PythonObject *object = (PythonObject*)PyLong_AsVoidPtr(PyDict_GetItemString(dict,"__charmObject__"));
+  //CmiLock(CsvAccess(pyLock));
+  ArrayElement1D *pyArray1 = dynamic_cast<ArrayElement1D*>(object);
+  ArrayElement2D *pyArray2 = dynamic_cast<ArrayElement2D*>(object);
+  ArrayElement3D *pyArray3 = dynamic_cast<ArrayElement3D*>(object);
+  ArrayElement4D *pyArray4 = dynamic_cast<ArrayElement4D*>(object);
+  ArrayElement5D *pyArray5 = dynamic_cast<ArrayElement5D*>(object);
+  ArrayElement6D *pyArray6 = dynamic_cast<ArrayElement6D*>(object);
+  //CmiUnlock(CsvAccess(pyLock));
   if (pyArray1) return Py_BuildValue("(i)", pyArray1->thisIndex);
   else if (pyArray2) return Py_BuildValue("(ii)", pyArray2->thisIndex.x, pyArray2->thisIndex.y);
   else if (pyArray3) return Py_BuildValue("(iii)", pyArray3->thisIndex.x, pyArray3->thisIndex.y, pyArray3->thisIndex.z);
@@ -78,11 +85,12 @@ static PyObject *CkPy_myindex(PyObject *self, PyObject *args) {
 // method to read a variable and convert it to a python object
 static PyObject *CkPy_read(PyObject *self, PyObject *args) {
   if (!PyArg_ParseTuple(args, "O:read")) return NULL;
-  CmiUInt4 pyReference = PyInt_AsLong(PyDict_GetItemString(PyModule_GetDict(PyImport_AddModule("__main__")),"__charmNumber__"));
-  CmiLock(CsvAccess(pyLock));
-  PythonObject *pyWorker = ((*CsvAccess(pyWorkers))[pyReference]).object;
-  CmiUnlock(CsvAccess(pyLock));
-  return pyWorker->read(args);
+  PyObject *dict = PyModule_GetDict(PyImport_AddModule("__main__"));
+  CmiUInt4 pyReference = PyInt_AsLong(PyDict_GetItemString(dict,"__charmNumber__"));
+  PythonObject *object = (PythonObject*)PyLong_AsVoidPtr(PyDict_GetItemString(dict,"__charmObject__"));
+  //CmiLock(CsvAccess(pyLock));
+  //CmiUnlock(CsvAccess(pyLock));
+  return object->read(args);
 }
 
 // method to convert a python object into a variable and write it
@@ -109,11 +117,10 @@ static PyObject *CkPy_write(PyObject *self, PyObject *args) {
     whatT = PyTuple_New(1);
     PyTuple_SET_ITEM(whatT, 0, what);
   }
-  CmiUInt4 pyReference = PyInt_AsLong(PyDict_GetItemString(PyModule_GetDict(PyImport_AddModule("__main__")),"__charmNumber__"));
-  CmiLock(CsvAccess(pyLock));
-  PythonObject *pyWorker = ((*CsvAccess(pyWorkers))[pyReference]).object;
-  CmiUnlock(CsvAccess(pyLock));
-  pyWorker->write(whereT, whatT);
+  PyObject *dict = PyModule_GetDict(PyImport_AddModule("__main__"));
+  CmiUInt4 pyReference = PyInt_AsLong(PyDict_GetItemString(dict,"__charmNumber__"));
+  PythonObject *object = (PythonObject*)PyLong_AsVoidPtr(PyDict_GetItemString(dict,"__charmObject__"));
+  object->write(whereT, whatT);
   Py_DECREF(whereT);
   Py_DECREF(whatT);
   Py_INCREF(Py_None);return Py_None;
@@ -136,6 +143,19 @@ PyMethodDef CkPy_MethodsDefault[] = {
   {NULL,      NULL}        /* Sentinel */
 };
 
+void PythonObject::replyIntValue(CcsDelayedReply *reply, CmiUInt4 *value) {
+  CkPrintf("[%d] PythonObject::replyIntValue\n",CkMyPe());
+  PythonReplyInt forward;
+  forward.reply = *reply;
+  forward.value = *value;
+  CkCallback cb(CkIndex_PythonCCS::forwardInt(0), pythonCcsProxy);
+  ArrayElement *array = dynamic_cast<ArrayElement *>(this);
+  Group *group = dynamic_cast<Group *>(this);
+  if (array != NULL) array->contribute(sizeof(PythonReplyInt), &forward, CkReduction::bitvec_and, cb);
+  else if (group != NULL) group->contribute(sizeof(PythonReplyInt), &forward, CkReduction::bitvec_and, cb);
+  else CcsSendDelayedReply(*reply, sizeof(CmiUInt4), (void *)value);
+}
+
 void PythonObject::pyRequest (CkCcsRequestMsg *msg) {
   PythonAbstract *pyAbstract = (PythonAbstract *)msg->data;
   pyAbstract->unpack();
@@ -160,17 +180,17 @@ void PythonObject::pyRequest (CkCcsRequestMsg *msg) {
 
 void PythonObject::print (PythonPrint *pyMsg, CcsDelayedReply *reply) {
   // ATTN: be sure that in all possible paths pyLock is released!
-  CmiLock(CsvAccess(pyLock));
+  //CmiLock(CsvAccess(pyLock));
   CmiUInt4 returnValue;
   pyMsg->unpack();
 
-  PythonTable::iterator iter = CsvAccess(pyWorkers)->find(pyMsg->interpreter);
-  if (iter == CsvAccess(pyWorkers)->end()) {
+  PythonTable::iterator iter = pyWorkers.find(pyMsg->interpreter);
+  if (iter == pyWorkers.end()) {
     // Malformed request!
     //CkPrintf("PythonCCS: print request on invalid interpreter\n");
-    CmiUnlock(CsvAccess(pyLock));
+    //CmiUnlock(CsvAccess(pyLock));
     returnValue = htonl(0);
-    CcsSendDelayedReply(*reply, sizeof(CmiUInt4), (void *)&returnValue);
+    replyIntValue(reply, &returnValue);
   } else {
     // it is a correct print request, parse it
 
@@ -178,9 +198,9 @@ void PythonObject::print (PythonPrint *pyMsg, CcsDelayedReply *reply) {
       // kill the pending client print request
       if (iter->second.clientReady == 1) {
        returnValue = htonl(0);
-       CcsSendDelayedReply(iter->second.client, sizeof(CmiUInt4), (void *)&returnValue);
+       replyIntValue(&iter->second.client, &returnValue);
       }
-      CmiUnlock(CsvAccess(pyLock));
+      //CmiUnlock(CsvAccess(pyLock));
       // do no return anything to the calling socket
       CcsNoDelayedReply(*reply);
       return;
@@ -190,12 +210,21 @@ void PythonObject::print (PythonPrint *pyMsg, CcsDelayedReply *reply) {
     if (iter->second.printed.length() > 0) {
       // send back to the client the string
       const char *str = iter->second.printed.c_str();
+      int length = strlen(str);
       //CkPrintf("sending data to the client\n");
-      CcsSendDelayedReply(*reply, strlen(str), str);
+      PythonReplyString *forward = new (length) PythonReplyString();
+      forward->reply = *reply;
+      memcpy(forward->data, str, length);
+      CkCallback cb(CkIndex_PythonCCS::forwardString(0), pythonCcsProxy);
+      ArrayElement *array = dynamic_cast<ArrayElement *>(this);
+      Group *group = dynamic_cast<Group *>(this);
+      if (array != NULL) array->contribute(sizeof(CcsDelayedReply)+length, forward, PythonCCS::reduceString, cb);
+      else if (group != NULL) group->contribute(sizeof(CcsDelayedReply)+length, forward, PythonCCS::reduceString, cb);
+      else CcsSendDelayedReply(*reply, length, str);
       iter->second.printed.erase();
       if (iter->second.clientReady == -1) {
        // after the client flush the printed buffer, delete the entry
-       CsvAccess(pyWorkers)->erase(pyMsg->interpreter);
+       pyWorkers.erase(pyMsg->interpreter);
       }
     } else {
       // nothing printed, store the client request if it will be waiting
@@ -203,33 +232,33 @@ void PythonObject::print (PythonPrint *pyMsg, CcsDelayedReply *reply) {
        // check if someone else has requested prints, if yes, kill the other
        if (iter->second.clientReady == 1) {
          returnValue = htonl(0);
-         CcsSendDelayedReply(iter->second.client, sizeof(CmiUInt4), (void *)&returnValue);
+         replyIntValue(&iter->second.client, &returnValue);
        }
        iter->second.client = *reply;
        iter->second.clientReady = 1;
       } else {
        // return null
        returnValue = htonl(0);
-       CcsSendDelayedReply(*reply, sizeof(CmiUInt4), (void *)&returnValue);
+       replyIntValue(reply, &returnValue);
       }
     }
-    CmiUnlock(CsvAccess(pyLock));
+    //CmiUnlock(CsvAccess(pyLock));
   }
 }
 
 void PythonObject::finished (PythonFinished *pyMsg, CcsDelayedReply *reply) {
    // ATTN: be sure that in all possible paths pyLock is released!
-  CmiLock(CsvAccess(pyLock));
+  //CmiLock(CsvAccess(pyLock));
   CmiUInt4 pyReference = pyMsg->interpreter;
   CmiUInt4 returnValue;
   pyMsg->unpack();
 
-  PythonTable::iterator iter = CsvAccess(pyWorkers)->find(pyMsg->interpreter);
-  if (iter == CsvAccess(pyWorkers)->end() || !iter->second.inUse) {
+  PythonTable::iterator iter = pyWorkers.find(pyMsg->interpreter);
+  if (iter == pyWorkers.end() || !iter->second.inUse) {
     //ckout <<"answering Finished yes"<<endl;
     returnValue = htonl(pyReference);
-    CcsSendDelayedReply(*reply, sizeof(CmiUInt4), (void *)&returnValue);
-    CmiUnlock(CsvAccess(pyLock));
+    replyIntValue(reply, &returnValue);
+    //CmiUnlock(CsvAccess(pyLock));
     return;
   }
 
@@ -239,7 +268,7 @@ void PythonObject::finished (PythonFinished *pyMsg, CcsDelayedReply *reply) {
     if (iter->second.finishReady) {
       // kill the previous requester
       returnValue = htonl(0);
-      CcsSendDelayedReply(iter->second.finish, sizeof(CmiUInt4), (void *)&returnValue);
+      replyIntValue(&iter->second.finish, &returnValue);
     }
     //ckout <<"queueing Finished request"<<endl;
     iter->second.finish = *reply;
@@ -247,16 +276,16 @@ void PythonObject::finished (PythonFinished *pyMsg, CcsDelayedReply *reply) {
   } else {
     //ckout <<"answering Finished no"<<endl;
     returnValue = htonl(0);
-    CcsSendDelayedReply(*reply, sizeof(CmiUInt4), (void *)&returnValue);
+    replyIntValue(reply, &returnValue);
   }
-  CmiUnlock(CsvAccess(pyLock));
+  //CmiUnlock(CsvAccess(pyLock));
 }
 
 void PythonObject::execute (CkCcsRequestMsg *msg, CcsDelayedReply *reply) {
   // ATTN: be sure that in all possible paths pyLock is released!
   PythonExecute *pyMsg = (PythonExecute *)msg->data;
-  PyEval_AcquireLock();
-  CmiLock(CsvAccess(pyLock));
+  //PyEval_AcquireLock();
+  //CmiLock(CsvAccess(pyLock));
   CmiUInt4 pyReference;
   CmiUInt4 returnValue;
 
@@ -266,12 +295,12 @@ void PythonObject::execute (CkCcsRequestMsg *msg, CcsDelayedReply *reply) {
   if (pyMsg->interpreter > 0) {
     // the user specified an interpreter, check if it is free
     PythonTable::iterator iter;
-    if ((iter=CsvAccess(pyWorkers)->find(pyMsg->interpreter))!=CsvAccess(pyWorkers)->end() && !iter->second.inUse && iter->second.clientReady!=-1) {
+    if ((iter=pyWorkers.find(pyMsg->interpreter))!=pyWorkers.end() && !iter->second.inUse && iter->second.clientReady!=-1) {
       // the interpreter already exists and it is neither in use, nor dead
       //CkPrintf("interpreter present and not in use\n");
       pyReference = pyMsg->interpreter;
+      PyEval_AcquireLock();
       PyThreadState_Swap(iter->second.pythread);
-      //PyEval_AcquireLock();
     } else {
       // ops, either the iterator does not exist or is already in use, return an
       // error to the client, we don't want to create a new interpreter if the
@@ -279,9 +308,9 @@ void PythonObject::execute (CkCcsRequestMsg *msg, CcsDelayedReply *reply) {
       //if (iter==CsvAccess(pyWorkers)->end()) CkPrintf("asked for an interpreter not present\n");
       //else CkPrintf("interpreter already in use\n");
       returnValue = htonl(0);
-      CcsSendDelayedReply(*reply, sizeof(CmiUInt4), (void *)&returnValue);
-      CmiUnlock(CsvAccess(pyLock));
-      PyEval_ReleaseLock();
+      replyIntValue(reply, &returnValue);
+      //CmiUnlock(CsvAccess(pyLock));
+      //PyEval_ReleaseLock();
       return;  // stop the execution
     }
   } else {
@@ -289,17 +318,17 @@ void PythonObject::execute (CkCcsRequestMsg *msg, CcsDelayedReply *reply) {
     //CkPrintf("creating new interpreter\n");
 
     // update the reference number, used to access the current chare
-    pyReference = ++CsvAccess(pyNumber);
-    CsvAccess(pyNumber) &= ~(1<<31);
-    ((*CsvAccess(pyWorkers))[pyReference]).object = this;
-    ((*CsvAccess(pyWorkers))[pyReference]).clientReady = 0;
+    pyReference = ++pyNumber;
+    pyNumber &= ~(1<<31);
+    //pyWorkers[pyReference].object = this;
+    pyWorkers[pyReference].clientReady = 0;
 
     // create the new interpreter
-    //PyEval_AcquireLock();
+    PyEval_AcquireLock();
     PyThreadState *pts = Py_NewInterpreter();
 
     CkAssert(pts != NULL);
-    ((*CsvAccess(pyWorkers))[pyReference]).pythread = pts;
+    pyWorkers[pyReference].pythread = pts;
 
     Py_InitModule("ck", CkPy_MethodsDefault);
     if (pyMsg->isHighLevel()) Py_InitModule("charm", getMethods());
@@ -309,6 +338,7 @@ void PythonObject::execute (CkCcsRequestMsg *msg, CcsDelayedReply *reply) {
     PyObject *dict = PyModule_GetDict(mod);
 
     PyDict_SetItemString(dict,"__charmNumber__",PyInt_FromLong(pyReference));
+    PyDict_SetItemString(dict,"__charmObject__",PyLong_FromVoidPtr(this));
     PyRun_String("import ck\nimport sys\n"
                 "ck.__doc__ = \"Ck module: basic charm routines\\n"
                 "printstr(str) -- print a string on the server\\n"
@@ -334,28 +364,28 @@ void PythonObject::execute (CkCcsRequestMsg *msg, CcsDelayedReply *reply) {
 
   }
 
-  ((*CsvAccess(pyWorkers))[pyReference]).inUse = true;
+  pyWorkers[pyReference].inUse = true;
   if (pyMsg->isKeepPrint()) {
-    ((*CsvAccess(pyWorkers))[pyReference]).isKeepPrint = true;
+    pyWorkers[pyReference].isKeepPrint = true;
   } else {
-    ((*CsvAccess(pyWorkers))[pyReference]).isKeepPrint = false;
+    pyWorkers[pyReference].isKeepPrint = false;
   }
 
   if (pyMsg->isWait()) {
-    ((*CsvAccess(pyWorkers))[pyReference]).finish = *reply;
-    ((*CsvAccess(pyWorkers))[pyReference]).finishReady = 1;
+    pyWorkers[pyReference].finish = *reply;
+    pyWorkers[pyReference].finishReady = 1;
   } else {
-    ((*CsvAccess(pyWorkers))[pyReference]).finishReady = 0;
+    pyWorkers[pyReference].finishReady = 0;
     // send back this number to the client, which is an ack
     ckout<<"new interpreter created "<<pyReference<<endl;
     returnValue = htonl(pyReference);
-    CcsSendDelayedReply(*reply, sizeof(CmiUInt4), (void *)&returnValue);
+    replyIntValue(reply, &returnValue);
   }
 
   //if (((*CsvAccess(pyWorkers))[pyReference]).object != this) ckout<<"object not this"<<endl;
   //else ckout<<"object ok"<<endl;
 
-  CmiUnlock(CsvAccess(pyLock));
+  //CmiUnlock(CsvAccess(pyLock));
 
   // run the program
   if (pyMsg->isHighLevel()) {
@@ -389,9 +419,9 @@ void PythonObject::executeThread(PythonExecute *pyMsg) {
 
   // store the self thread for future suspention if high level execution
   if (pyMsg->isHighLevel()) {
-    CmiLock(CsvAccess(pyLock));
-    ((*CsvAccess(pyWorkers))[pyReference]).thread=CthSelf();
-    CmiUnlock(CsvAccess(pyLock));
+    //CmiLock(CsvAccess(pyLock));
+    pyWorkers[pyReference].thread=CthSelf();
+    //CmiUnlock(CsvAccess(pyLock));
   }
 
   // decide whether it is iterative or not
@@ -405,13 +435,13 @@ void PythonObject::executeThread(PythonExecute *pyMsg) {
       PyErr_Fetch(&ptype, &pvalue, &ptraceback);
       PyObject *strP = PyObject_Str(ptype);
       char *str = PyString_AsString(strP);
-      Ck_printclient(pyReference, str);
+      Ck_printclient(this, pyReference, str);
       //CkPrintf("%s\n",str);
       Py_DECREF(strP);
-      Ck_printclient(pyReference, ": ");
+      Ck_printclient(this, pyReference, ": ");
       strP = PyObject_Str(pvalue);
       str = PyString_AsString(strP);
-      Ck_printclient(pyReference, str);
+      Ck_printclient(this, pyReference, str);
       //CkPrintf("%s\n",str);
       Py_DECREF(strP);
       //PyObject_Print(ptype, stdout, 0);
@@ -422,6 +452,8 @@ void PythonObject::executeThread(PythonExecute *pyMsg) {
       //if (ptraceback) CkPrintf("   %d %d %d %d\n",PyType_Check(ptraceback),PyString_Check(ptraceback),PyList_Check(ptraceback),PyTuple_Check(ptraceback));
     }
   } else {
+    CkPrintf("userCode: |%s|",pyMsg->code);
+    CkPrintf("method: |%s|",pyMsg->methodName.methodName);
     // compile the program
     char *userCode = pyMsg->code.code;
     struct _node* programNode = PyParser_SimpleParseString(userCode, Py_file_input);
@@ -465,14 +497,16 @@ void PythonObject::executeThread(PythonExecute *pyMsg) {
     }
 
     // create the container for the data
-    PyRun_String("class Particle:\n\tpass\n\n", Py_file_input, dict, dict);
-    PyObject *part = PyRun_String("Particle()", Py_eval_input, dict, dict);
+    PyRun_String("class CharmContainer:\n\tpass\n\n", Py_file_input, dict, dict);
+    PyObject *part = PyRun_String("CharmContainer()", Py_eval_input, dict, dict);
     PyObject *arg = PyTuple_New(1);
-    PyTuple_SetItem(arg, 0, part);
+    PyObject *oldArg = part;
 
     // construct the iterator calling the user defined method in the interiting class
     PythonIterator *userIterator = pyMsg->info.info;
     int more = buildIterator(part, userIterator);
+    if (oldArg != part) Py_DECREF(oldArg);
+    PyTuple_SetItem(arg, 0, part);
 
     // iterate over all the provided iterators from the user class
     PyObject *result;
@@ -480,10 +514,15 @@ void PythonObject::executeThread(PythonExecute *pyMsg) {
       result = PyObject_CallObject(item, arg);
       if (!result) {
        CkPrintf("Python Call error\n");
-        PyErr_Print();
+        //PyErr_Print();
        break;
       }
+      oldArg = part;
       more = nextIteratorUpdate(part, result, userIterator);
+      if (oldArg != part) {
+        Py_DECREF(oldArg);
+        PyTuple_SetItem(arg, 0, part);
+      }
       Py_DECREF(result);
     }
 
@@ -505,172 +544,35 @@ void PythonObject::cleanup (PythonExecute *pyMsg, PyThreadState *pts, CmiUInt4 p
   CmiUInt4 returnValue;
 
   //ckout <<"cleanup called"<<endl;
-  CmiLock(CsvAccess(pyLock));
+  //CmiLock(CsvAccess(pyLock));
   // if there is someone waiting for finish, send ackowledge
-  if (((*CsvAccess(pyWorkers))[pyReference]).finishReady) {
+  if (pyWorkers[pyReference].finishReady) {
     //ckout <<"answering the client finish"<<endl;
     returnValue = htonl(pyReference);
-    CcsSendDelayedReply(((*CsvAccess(pyWorkers))[pyReference]).finish, sizeof(CmiUInt4), (void *)&returnValue);
-    ((*CsvAccess(pyWorkers))[pyReference]).finishReady = 0;
+    replyIntValue(&pyWorkers[pyReference].finish, &returnValue);
+    pyWorkers[pyReference].finishReady = 0;
   }
 
   //ckout << "options"<<pyMsg->isPersistent()<<endl;
-  ((*CsvAccess(pyWorkers))[pyReference]).inUse = false;
+  pyWorkers[pyReference].inUse = false;
   if (!pyMsg->isPersistent()) {
     Py_EndInterpreter(pts);
-    ((*CsvAccess(pyWorkers))[pyReference]).clientReady = -1;
+    pyWorkers[pyReference].clientReady = -1;
   }
   PyEval_ReleaseLock();
 
-  if (!pyMsg->isPersistent() && ((*CsvAccess(pyWorkers))[pyReference]).printed.length()==0) {
+  if (!pyMsg->isPersistent() && pyWorkers[pyReference].printed.length()==0) {
     // destroy the entry in the map
     //CkPrintf("destroyed interpreter\n");
-    CsvAccess(pyWorkers)->erase(pyReference);
+    pyWorkers.erase(pyReference);
   }
-  CmiUnlock(CsvAccess(pyLock));
+  //CmiUnlock(CsvAccess(pyLock));
 }
 
-/*
-void PythonObject::iterate (CkCcsRequestMsg *msg) {
-
-  // update the reference number, used to access the current chare
-  CmiLock(CsvAccess(pyLock));
-  CmiUInt4 pyReference = CsvAccess(pyNumber)++;
-  CsvAccess(pyNumber) &= ~(1<<31);
-  ((*CsvAccess(pyWorkers))[pyReference]).object = this;
-  CmiUnlock(CsvAccess(pyLock));
-
-  // send back this number to the client
-  CcsSendDelayedReply(msg->reply, 1, (void *)&pyReference);
-
-  // create the new interpreter
-  PyEval_AcquireLock();
-  PyThreadState *pts = Py_NewInterpreter();
-  Py_InitModule("ck", CkPy_MethodsDefault);
-
-  // insert into the dictionary a variable with the reference number
-  PyObject *mod = PyImport_AddModule("__main__");
-  PyObject *dict = PyModule_GetDict(mod);
-
-  PyDict_SetItemString(dict,"__charmNumber__",PyInt_FromLong(pyReference));
-
-  // compile the program
-  char *userCode = (char *)msg->data;
-  struct _node* programNode = PyParser_SimpleParseString(userCode, Py_file_input);
-  if (programNode==NULL) {
-    CkPrintf("Program error\n");
-    // distroy map element in pyWorkers and terminate interpreter
-    Py_EndInterpreter(pts);
-    PyEval_ReleaseLock();
-    CmiLock(CsvAccess(pyLock));
-    CsvAccess(pyWorkers)->erase(pyReference);
-    CmiUnlock(CsvAccess(pyLock));
-    delete msg;
-    return;
-  }
-  PyCodeObject *program = PyNode_Compile(programNode, "");
-  if (program==NULL) {
-    CkPrintf("Program error\n");
-    PyNode_Free(programNode);
-    // distroy map element in pyWorkers and terminate interpreter
-    Py_EndInterpreter(pts);
-    PyEval_ReleaseLock();
-    CmiLock(CsvAccess(pyLock));
-    CsvAccess(pyWorkers)->erase(pyReference);
-    CmiUnlock(CsvAccess(pyLock));
-    delete msg;
-    return;
-  }
-  PyObject *code = PyEval_EvalCode(program, dict, dict);
-  if (code==NULL) {
-    CkPrintf("Program error\n");
-    PyNode_Free(programNode);
-    Py_DECREF(program);
-    // distroy map element in pyWorkers and terminate interpreter
-    Py_EndInterpreter(pts);
-    PyEval_ReleaseLock();
-    CmiLock(CsvAccess(pyLock));
-    CsvAccess(pyWorkers)->erase(pyReference);
-    CmiUnlock(CsvAccess(pyLock));
-    delete msg;
-    return;
-  }
-
-  // load the user defined method
-  char *userMethod = userCode + strlen(userCode) + 1;
-  PyObject *item = PyDict_GetItemString(dict, userMethod);
-  if (item==NULL) {
-    CkPrintf("Method not found\n");
-    PyNode_Free(programNode);
-    Py_DECREF(program);
-    Py_DECREF(code);
-    // distroy map element in pyWorkers and terminate interpreter
-    Py_EndInterpreter(pts);
-    PyEval_ReleaseLock();
-    CmiLock(CsvAccess(pyLock));
-    CsvAccess(pyWorkers)->erase(pyReference);
-    CmiUnlock(CsvAccess(pyLock));
-    delete msg;
-    return;
-  }
-
-  // create the container for the data
-  PyRun_String("class Particle:\n\tpass\n\n", Py_file_input, dict, dict);
-  PyObject *part = PyRun_String("Particle()", Py_eval_input, dict, dict);
-  PyObject *arg = PyTuple_New(1);
-  PyTuple_SetItem(arg, 0, part);
-
-  // construct the iterator calling the user defined method in the interiting class
-  void *userIterator = (void *)(userMethod + strlen(userMethod) + 1);
-  int more = buildIterator(part, userIterator);
-
-  // iterate over all the provided iterators from the user class
-  PyObject *result;
-  while (more) {
-    result = PyObject_CallObject(item, arg);
-    if (!result) {
-      CkPrintf("Python Call error\n");
-      break;
-    }
-    more = nextIteratorUpdate(part, result, userIterator);
-    Py_DECREF(result);
-  }
-
-  Py_DECREF(part);
-  Py_DECREF(arg);
-  PyNode_Free(programNode);
-  Py_DECREF(program);
-  Py_DECREF(code);
-
-  // distroy map element in pyWorkers and terminate interpreter
-  Py_EndInterpreter(pts);
-  PyEval_ReleaseLock();
-  CmiLock(CsvAccess(pyLock));
-  CsvAccess(pyWorkers)->erase(pyReference);
-  CmiUnlock(CsvAccess(pyLock));
-  delete msg;
-}
-*/
-
 void PythonObject::getPrint(CkCcsRequestMsg *msg) {
 
 }
 
-static void initializePythonDefault(void) {
-  CsvInitialize(CmiUInt, pyNumber);
-  CsvAccess(pyNumber) = 0;
-  CsvInitialize(PythonTable *,pyWorkers);
-  CsvAccess(pyWorkers) = new PythonTable();
-  CsvInitialize(CmiNodeLock, pyLock);
-  CsvAccess(pyLock) = CmiCreateLock();
-  CtvInitialize(PyObject *,pythonReturnValue);
-
-  Py_Initialize();
-  PyEval_InitThreads();
-
-  PyEval_ReleaseLock();
-}
-
 // a bunch of routines to ease the user code
 void PythonObject::pythonSetString(PyObject *arg, char *descr, char *value) {
   PyObject *tmp = PyString_FromString(value);
@@ -763,29 +665,44 @@ void PythonObject::pythonGetComplex(PyObject *arg, char *descr, double *real, do
   Py_DECREF(tmp);
 }
 
+void PythonObject::pythonSetPointer(PyObject *arg, char *descr, void *ptr) {
+  PyObject *tmp = PyLong_FromVoidPtr(ptr);
+  PyObject_SetAttrString(arg, descr, tmp);
+  Py_DECREF(tmp);
+}
+
+void PythonObject::pythonGetPointer(PyObject *arg, char *descr, void **ptr) {
+  PyObject *tmp = PyObject_GetAttrString(arg, descr);
+  *ptr = PyLong_AsVoidPtr(tmp);
+  Py_DECREF(tmp);
+}
+
 PyObject *PythonObject::pythonGetArg(int handle) {
-  CmiLock(CsvAccess(pyLock));
-  PyObject *result = ((*CsvAccess(pyWorkers))[handle]).arg;
-  CmiUnlock(CsvAccess(pyLock));
+  //CmiLock(CsvAccess(pyLock));
+  PyObject *result = pyWorkers[handle].arg;
+  //CmiUnlock(CsvAccess(pyLock));
   return result;
 }
 
 void PythonObject::pythonReturn(int handle) {
-  CmiLock(CsvAccess(pyLock));
-  CthThread handleThread = ((*CsvAccess(pyWorkers))[handle]).thread;
-  *((*CsvAccess(pyWorkers))[handle]).result = 0;
-  CmiUnlock(CsvAccess(pyLock));
-  CthAwaken(handleThread);
+  // The return value is now set to zero before calling the high-level function, so here
+  // we don't need to do anything.
+  //CmiLock(CsvAccess(pyLock));
+  //CthThread handleThread = ((*CsvAccess(pyWorkers))[handle]).thread;
+  //*((*CsvAccess(pyWorkers))[handle]).result = 0;
+  //CmiUnlock(CsvAccess(pyLock));
+  //CthAwaken(handleThread);
 }
 
 void PythonObject::pythonReturn(int handle, PyObject* data) {
-  CmiLock(CsvAccess(pyLock));
-  CthThread handleThread = ((*CsvAccess(pyWorkers))[handle]).thread;
-  *((*CsvAccess(pyWorkers))[handle]).result = data;
-  CmiUnlock(CsvAccess(pyLock));
-  CthAwaken(handleThread);
+  //CmiLock(CsvAccess(pyLock));
+  //CthThread handleThread = ((*CsvAccess(pyWorkers))[handle]).thread;
+  * pyWorkers[handle].result = data;
+  //CmiUnlock(CsvAccess(pyLock));
+  //CthAwaken(handleThread);
 }
 
+/*
 void PythonObject::pythonAwake(int handle) {
   CmiLock(CsvAccess(pyLock));
   PyThreadState *handleThread = ((*CsvAccess(pyWorkers))[handle]).pythread;
@@ -797,5 +714,62 @@ void PythonObject::pythonAwake(int handle) {
 void PythonObject::pythonSleep(int handle) {
   PyEval_ReleaseLock();
 }
+*/
+
+PythonCCS::PythonCCS(CkArgMsg *arg) {
+  pythonCcsProxy = thishandle;
+}
+
+CkReductionMsg *pythonCombinePrint(int nMsg, CkReductionMsg **msgs) {
+  // the final length is the sum of all the NULL-terminated strings, minus
+  // the initial CcsDelayedReply structs and the terminating NULL characters
+  // which are present only once in the final message
+  int length = - (nMsg-1) * sizeof(CcsDelayedReply);
+  for (int i=0; i<nMsg; ++i) {
+    length += msgs[i]->getSize();
+  }
+  
+  CkReductionMsg *result = CkReductionMsg::buildNew(length,NULL);
+  
+  PythonReplyString *data = (PythonReplyString*)(result->getData());
+  data->reply = ((PythonReplyString*)msgs[0]->getData())->reply;
+  char *cur=data->data;
+  for (int i=0; i<nMsg; ++i) {
+    int messageBytes=msgs[i]->getSize() - sizeof(CcsDelayedReply);
+    memcpy((void *)cur,(void *)((PythonReplyString*)msgs[i]->getData())->data,messageBytes);
+    cur+=messageBytes;
+  }
+  return result;
+}
+
+void PythonCCS::forwardString(CkReductionMsg *msg) {
+  PythonReplyString *forward = (PythonReplyString *)msg->getData();
+  CcsSendDelayedReply(forward->reply, msg->getSize()-sizeof(CcsDelayedReply), (void *)forward->data);
+}
+
+void PythonCCS::forwardInt(CkReductionMsg *msg) {
+  CkPrintf("PythonCCS::forwardInt\n");
+  PythonReplyInt *forward = (PythonReplyInt *)msg->getData();
+  CcsSendDelayedReply(forward->reply, sizeof(CmiUInt4), (void *)&forward->value);
+}
+
+CkReduction::reducerType PythonCCS::reduceString;
+
+static void initializePythonDefault(void) {
+  //CsvInitialize(CmiUInt, pyNumber);
+  //CsvAccess(pyNumber) = 0;
+  //CsvInitialize(PythonTable *,pyWorkers);
+  //CsvAccess(pyWorkers) = new PythonTable();
+  //CsvInitialize(CmiNodeLock, pyLock);
+  //CsvAccess(pyLock) = CmiCreateLock();
+  CtvInitialize(PyObject *,pythonReturnValue);
+
+  PythonCCS::reduceString = CkReduction::addReducer(pythonCombinePrint);
+  
+  Py_Initialize();
+  PyEval_InitThreads();
+
+  PyEval_ReleaseLock();
+}
 
 #include "PythonCCS.def.h"
index 74e913c1ee4234685624c7d102937ccae1c0be5c..d9988e3948f5751cacf22c9543f323029e76d624 100644 (file)
@@ -1,3 +1,10 @@
 module PythonCCS {
    initnode void initializePythonDefault(void);
+   readonly CProxy_PythonCCS pythonCcsProxy;
+
+   mainchare PythonCCS {
+     entry PythonCCS(CkArgMsg *arg);
+     entry void forwardString(CkReductionMsg *msg);
+     entry void forwardInt(CkReductionMsg *msg);
+   }
 }
index 3f0997633fe1fe75fc6c8e086d99e5951200dc46..5035016b0fdbd4f91b32fc5067a44c8e24ac1e8a 100644 (file)
@@ -5,10 +5,11 @@
 #define __CKPYTHON_H
 
 #include "ckcallback-ccs.h"
-#include "python/Python.h"
-#include "python/compile.h"
-#include "python/eval.h"
-#include "python/node.h"
+#include "./pythonIncludes.h"
+//#include "python/Python.h"
+//#include "python/compile.h"
+//#include "python/eval.h"
+//#include "python/node.h"
 #include "PythonCCS.decl.h"
 #include "PythonCCS-client.h"
 #include "string"
 
 extern PyMethodDef CkPy_MethodsDefault[];
 
+typedef struct {
+  //PythonObject *object; /* The c++ object running the job */
+  bool inUse;
+  bool isKeepPrint;
+  PyObject *arg;
+  PyObject **result;
+  CthThread thread;       /* The charm thread running the python code */
+  PyThreadState *pythread; /* The python interpreter interpreting the code */
+
+  int clientReady; /* whether or not a client has sent a request for print */
+  /* meanings of clientReady:
+     1  - there is a client wainting for data
+     0  - no client waiting for data
+     -1 - no client waiting, and the current structure is alive only because of
+     "KeepPrint". it has to be deleted when a client synchonizes
+  */
+  CcsDelayedReply client; /* Where to send the printed data when ready */
+
+  int finishReady; /* wheather or not a client is waiting to be notified of
+                     script finish */
+  /* meanings of finishReady:
+     1  - there is a client waiting
+     0  - no client is waiting
+  */
+  CcsDelayedReply finish; /* Where to send the ack of termination */
+
+  std::string printed; /* Union of all printed string and not yet shipped to the client */
+} PythonStruct;
+typedef std::map<CmiUInt4,PythonStruct> PythonTable;
+
 class PythonObject {
   static PyMethodDef CkPy_MethodsCustom[];
   static char* CkPy_MethodsCustomDoc;
  public:
+  CmiUInt4 pyNumber;
+  PythonTable pyWorkers;
+
+  PythonObject() : pyNumber(0) { }
   void pyRequest(CkCcsRequestMsg *msg);
   void execute(CkCcsRequestMsg *msg, CcsDelayedReply *reply);
   void print(PythonPrint *pyMsg, CcsDelayedReply *reply);
   void finished(PythonFinished *pyMsg, CcsDelayedReply *reply);
 
+  void replyIntValue(CcsDelayedReply *reply, CmiUInt4 *value);
   void cleanup(PythonExecute *pyMsg, PyThreadState *pts, CmiUInt4 pyVal);
   void getPrint(CkCcsRequestMsg *msg);
   static void _callthr_executeThread(CkThrCallArg *impl_arg);
@@ -48,6 +84,7 @@ class PythonObject {
   void pythonSetLong(PyObject*, char*, double);
   void pythonSetFloat(PyObject*, char*, double);
   void pythonSetComplex(PyObject*, char*, double, double);
+  void pythonSetPointer(PyObject*, char*, void*);
 
   void pythonGetString(PyObject*, char*, char**);
   void pythonGetInt(PyObject*, char*, long*);
@@ -56,6 +93,7 @@ class PythonObject {
   void pythonGetLong(PyObject*, char*, double*);
   void pythonGetFloat(PyObject*, char*, double*);
   void pythonGetComplex(PyObject*, char*, double*, double*);
+  void pythonGetPointer(PyObject*, char*, void**);
 
   // utility functions to deal with threads
   PyObject *pythonGetArg(int);
@@ -75,44 +113,51 @@ class PythonObject {
   // methods to create iterators for iterative python invocations
   // buildIterator: input a PyObject, which is an empty class to be filled with data, and a void pointer describing over what to iterate (user defined format). Should return 1, if it returns 0 no computation is done
   // nextIteratorUpdate: input a PyObject to be filled with the next iterator, this contains the previous iterator, so if the python code modified the object, here the new information can be found. A Python object with the result returned by the python code, and the description of the iterator (as in buildIterator). Return 1 if there is a new object, 0 if there are no more objects in the iterator.
-  virtual int buildIterator(PyObject*, void*) {CkAbort("PythonCCS: Method buildIterator should be reimplemented"); return 0; };
-  virtual int nextIteratorUpdate(PyObject*, PyObject*, void*) {CkAbort("PythonCCS: Method nextIteratorUpdate should be reimplemented"); return 0; };
+  virtual int buildIterator(PyObject*&, void*) {CkAbort("PythonCCS: Method buildIterator should be reimplemented"); return 0; };
+  virtual int nextIteratorUpdate(PyObject*&, PyObject*, void*) {CkAbort("PythonCCS: Method nextIteratorUpdate should be reimplemented"); return 0; };
 
 };
 
-typedef struct {
-  PythonObject *object; /* The c++ object running the job */
-  bool inUse;
-  bool isKeepPrint;
-  PyObject *arg;
-  PyObject **result;
-  CthThread thread;       /* The charm thread running the python code */
-  PyThreadState *pythread; /* The python interpreter interpreting the code */
-
-  int clientReady; /* whether or not a client has sent a request for print */
-  /* meanings of clientReady:
-     1  - there is a client wainting for data
-     0  - no client waiting for data
-     -1 - no client waiting, and the current structure is alive only because of
-     "KeepPrint". it has to be deleted when a client synchonizes
-  */
-  CcsDelayedReply client; /* Where to send the printed data when ready */
-
-  int finishReady; /* wheather or not a client is waiting to be notified of
-                     script finish */
-  /* meanings of finishReady:
-     1  - there is a client waiting
-     0  - no client is waiting
-  */
-  CcsDelayedReply finish; /* Where to send the ack of termination */
+//CsvExtern(CmiNodeLock, pyLock);
+//CsvExtern(PythonTable *, pyWorkers);
+//CsvExtern(CmiUInt4, pyNumber);
+CtvExtern(PyObject *, pythonReturnValue);
 
-  std::string printed; /* Union of all printed string and not yet shipped to the client */
-} PythonStruct;
-typedef std::map<CmiUInt4,PythonStruct> PythonTable;
+typedef struct PythonReplyInt {
+  CcsDelayedReply reply;
+  CmiUInt4 value;
+} PythonReplyInt;
+
+typedef struct PythonReplyString {
+  CcsDelayedReply reply;
+  char data[1];
+  
+  void *operator new(size_t size, const int length) {
+    return malloc(size+length);
+  }
+} PythonReplyString;
+
+class PythonCCS : public CBase_PythonCCS {
+ public:
+  PythonCCS(CkArgMsg *arg);
+  void forwardString(CkReductionMsg *msg);
+  void forwardInt(CkReductionMsg *msg);
+  
+  static CkReduction::reducerType reduceString;
+};
 
-CsvExtern(CmiNodeLock, pyLock);
-CsvExtern(PythonTable *, pyWorkers);
-CsvExtern(CmiUInt4, pyNumber);
-CtvExtern(PyObject *, pythonReturnValue);
+class CkCallbackPython : public CkCallbackResumeThread {
+ public:
+   ~CkCallbackPython(void) {
+     void *res = thread_delay();
+     if (result != NULL) *result = res;
+   }
+   void *thread_delay(void) const {
+     PyEval_ReleaseLock();
+     void *res = impl_thread_delay();
+     PyEval_AcquireLock();
+     return res;
+   }
+};
 
 #endif //__CKPYTHON_H
diff --git a/src/libs/ck-libs/pythonCCS/charmdebug-python.C b/src/libs/ck-libs/pythonCCS/charmdebug-python.C
new file mode 100644 (file)
index 0000000..74d5a01
--- /dev/null
@@ -0,0 +1,149 @@
+#include "charmdebug_python.decl.h"
+
+//CpvExtern(CkHashtable_c, ccsTab);
+class CpdPython : public CBase_CpdPython {
+public:
+  CpdPython (CkArgMsg *msg) {
+    ((CProxy_CpdPython)thishandle).registerPython("CpdPython");
+    //CkCallback cb(CkIndex_CpdPython::pyRequest(0),thishandle);
+    //CcsRegisterHandler("pycode", cb);
+    CProxy_CpdPythonGroup group = CProxy_CpdPythonGroup::ckNew();
+    group.registerPython("CpdPythonGroup");
+    //CcsRegisterHandler("CpdPythonGroup", CkCallback(CkIndex_CpdPythonGroup::pyRequest(0),group));
+    //CkPrintf("CpdPython registered\n");
+    //char *string = "pycode";
+    //CkAssert(CkHashtableGet(CpvAccess(ccsTab),(void *)&string) != NULL);
+  }
+  void get(int handle) {
+    CkPrintf("CpdPython::get\n");
+  }
+};
+
+class CpdPythonGroup : public CBase_CpdPythonGroup {
+public:
+  CpdPythonGroup() {
+    //CkPrintf("[%d] CpdPythonGroup::constructor\n",CkMyPe());
+  }
+
+  int buildIterator(PyObject*&, void*);
+  int nextIteratorUpdate(PyObject*&, PyObject*, void*);
+  
+  void getArray(int handle);
+  void getValue(int handle);
+  void getCast(int handle);
+  void getStatic(int handle);
+};
+
+int CpdPythonGroup::buildIterator(PyObject *&data, void *iter) {
+  int group = ntohl(*(int*)iter);
+  CkGroupID id;
+  id.idx = group;
+  void *ptr = CkLocalBranch(id);
+  data = PyLong_FromVoidPtr(ptr);
+  CkPrintf("[%d] Building iterator for %i: %p\n", CkMyPe(), group, ptr);
+  return 1;
+}
+
+int CpdPythonGroup::nextIteratorUpdate(PyObject *&data, PyObject *result, void *iter) {
+  CkPrintf("[%d] Asked for next iterator\n",CkMyPe());
+  return 0;
+}
+
+void CpdPythonGroup::getArray(int handle) {
+  PyObject *arg = pythonGetArg(handle);
+  PyObject *obj, *type;
+  int num, size;
+  if (PyArg_ParseTuple(arg, "OOii", &obj, &type, &num, &size) == 0) return;
+  char *ptr = (char*)PyLong_AsVoidPtr(obj);
+  ptr += num * size;
+  pythonReturn(handle, PyLong_FromVoidPtr(ptr));
+}
+
+void CpdPythonGroup::getValue(int handle) {
+  PyObject *arg = pythonGetArg(handle);
+  PyObject *obj, *type;
+  int offset;
+  char *name, restype;
+  if (PyArg_ParseTuple(arg, "OOsic", &obj, &type, &name, &offset, &restype) == 0) return;
+  char *ptr = (char*)PyLong_AsVoidPtr(obj);
+  ptr += offset;
+  PyObject *result = NULL;
+  switch (restype) {
+  case 'p':
+    result = PyLong_FromVoidPtr(ptr);
+    break;
+  case 'b':
+    result = Py_BuildValue("b", *(char*)ptr);
+    break;
+  case 'h':
+    result = Py_BuildValue("h", *(short*)ptr);
+    break;
+  case 'i':
+    result = Py_BuildValue("i", *(int*)ptr);
+    break;
+  case 'l':
+    result = Py_BuildValue("l", *(long*)ptr);
+    break;
+  case 'f':
+    result = Py_BuildValue("f", *(float*)ptr);
+    break;
+  case 'd':
+    result = Py_BuildValue("d", *(double*)ptr);
+    break;
+  case 's':
+    result = Py_BuildValue("s", *(char**)ptr);
+    break;
+  }
+  pythonReturn(handle, result);
+}
+
+void CpdPythonGroup::getCast(int handle) {
+  PyObject *arg = pythonGetArg(handle);
+  PyObject *obj, *type, *newtype;
+  int offset;
+  if (PyArg_ParseTuple(arg, "OOOi", &obj, &type, &newtype, &offset) == 0) return;
+  char *ptr = (char*)PyLong_AsVoidPtr(obj);
+  ptr += offset;
+  pythonReturn(handle, PyLong_FromVoidPtr(ptr));
+}
+
+void CpdPythonGroup::getStatic(int handle) {
+  PyObject *arg = pythonGetArg(handle);
+  PyObject *location;
+  char *name, restype;
+  CkPrintf("Parsing arguments\n");
+  if (PyArg_ParseTuple(arg, "sOc", &name, &location, &restype) == 0) return;
+  CkPrintf("Arguments parsed\n");
+  char *ptr = (char*)PyLong_AsVoidPtr(location);
+  CkPrintf("Pointer: %p",ptr);
+  PyObject *result = NULL;
+  switch (restype) {
+  case 'p':
+    result = PyLong_FromVoidPtr(ptr);
+    break;
+  case 'b':
+    result = Py_BuildValue("b", *(char*)ptr);
+    break;
+  case 'h':
+    result = Py_BuildValue("h", *(short*)ptr);
+    break;
+  case 'i':
+    result = Py_BuildValue("i", *(int*)ptr);
+    break;
+  case 'l':
+    result = Py_BuildValue("l", *(long*)ptr);
+    break;
+  case 'f':
+    result = Py_BuildValue("f", *(float*)ptr);
+    break;
+  case 'd':
+    result = Py_BuildValue("d", *(double*)ptr);
+    break;
+  case 's':
+    result = Py_BuildValue("s", *(char**)ptr);
+    break;
+  }
+  pythonReturn(handle, result);
+}
+
+#include "charmdebug_python.def.h"
diff --git a/src/libs/ck-libs/pythonCCS/charmdebug-python.ci b/src/libs/ck-libs/pythonCCS/charmdebug-python.ci
new file mode 100644 (file)
index 0000000..24ccae7
--- /dev/null
@@ -0,0 +1,14 @@
+module charmdebug_python {
+  mainchare [python] CpdPython {
+    entry CpdPython(CkArgMsg*);
+    entry [python] void get(int);
+  };
+  
+  group [python] CpdPythonGroup {
+    entry CpdPythonGroup();
+    entry [python] void getArray(int);
+    entry [python] void getValue(int);
+    entry [python] void getCast(int);
+    entry [python] void getStatic(int);
+  };
+};
\ No newline at end of file
index 43edc0a98cb4bf8a4ff8d6e4db1a7dbda859a61f..9fa2ef59c345de92dffbee080c5d6e2fed662d50 100644 (file)
@@ -74,11 +74,14 @@ AMPIF: AMPIC
 
 f90charm: charm++ $(L)/libf90charm.a
 
-default_libs: multicast
+default_libs: multicast pythonCCS
 
 multicast:
        cd libs/ck-libs/multicast && $(MAKE)
 
+pythonCCS:
+       cd libs/ck-libs/pythonCCS && $(MAKE)
+
 translators: charmxi conv-cpm
 
 pose:  charm++
@@ -358,7 +361,7 @@ LIBCONV_UTIL=pup_util.o pup_toNetwork.o pup_toNetwork4.o            \
 
 LIBCONV_UTILF=pup_f.o
 
-converse: basics
+converse: basics converse-target
        $(MAKE) QuickThreads/libqt.a
        $(MAKE) converse-target
 
index 95001addf575376ea0b3c8ba6580e9821c2b89b1..fc167659a57456cc9d136c064f6611d5c03a742b 100755 (executable)
@@ -52,6 +52,8 @@ OPTS_LDXX=""
 OPTS_PIC="$CMK_PIC"
 test -z "$OPTS_PIC" && OPTS_PIC='-fpic'
 
+CHARMDEBUG=""
+LINK_PYTHON=""
 OBJECT=""
 POST_LANGUAGE=""
 POST_LIBRARIES=""    
@@ -311,6 +313,50 @@ printVersion()
        echo Charm++ Version $version
 }
 
+
+##############################################################################
+#
+# The following section identifies CHARMBIN, the charm binary-directory.
+#
+##############################################################################
+
+ORIGDIR=`pwd`
+
+# Try to find CHARMBIN by looking in directory where charmc is
+
+findCharmBin $0
+
+FIRST_THREE=`uname -s | awk '{print substr($1,1,3)}' `
+if [ "$FIRST_THREE" = "CYG" ]
+then
+# Running on a windows system-- append .exe to file names
+       PROG_EXT=".exe"
+fi
+
+CHARMLIB="$CHARMBIN/../lib"
+CHARMINC="$CHARMBIN/../include"
+CHARMLIBSO=
+if test -d "$CHARMBIN/../lib_so" 
+then
+  CHARMLIBSO=`cd $CHARMBIN/../lib_so 2>/dev/null && pwd`
+  #getting absolute path is harder than thought because of symbolic links and ..
+  #ksh needs cd -P to resolve werid symbolic links, however -P is not portable
+  #csh is ok too if it exists 
+  test -z "$CHARMLIBSO" && CHARMLIBSO=`cd -P $CHARMBIN/../lib_so 2>/dev/null && pwd`
+  test -z "$CHARMLIBSO" && CHARMLIBSO=`csh -c "cd $CHARMBIN/../lib_so >& /dev/null && pwd"`
+  test -z "$CHARMLIBSO" && echo "$CHARMBIN/../lib_so: not found" && exit 1
+fi
+
+################################
+# Preload configuration script
+################################
+Debug "About to preload machine config script"
+Debug "Preload config script, setting defaults..."
+
+[ ! -r $CHARMINC/conv-config.sh ] && Abort "Cannot find conv-config.sh in $CHARMINC"
+. $CHARMINC/conv-config.sh $CHARMINC
+
+
 ##############################################################################
 #
 # Parse the arguments
@@ -368,6 +414,15 @@ do
                shift
                ;;
 
+        "-debug")
+                # Requested support from charmdebug: add some modules and libraries
+                CHARMDEBUG=1
+                MEMORY="charmdebug"
+                if [ -n "$CMK_BUILD_PYTHON" ]; then
+                    AddModules PythonCCS charmdebug_python
+                fi
+                ;;
+
        "-module"|"-modules")
                AddModules `echo $1 | sed -e 's/,/ /g'`
                shift
@@ -661,42 +716,11 @@ trap 'End 1' 2
 # Process original command-line arguments
 processArgs "$@"
 
-
-##############################################################################
-#
-# The following section identifies CHARMBIN, the charm binary-directory.
-#
-##############################################################################
-
-ORIGDIR=`pwd`
-
-# Try to find CHARMBIN by looking in directory where charmc is
-
-findCharmBin $0
-
-FIRST_THREE=`uname -s | awk '{print substr($1,1,3)}' `
-if [ "$FIRST_THREE" = "CYG" ]
-then
-# Running on a windows system-- append .exe to file names
-       PROG_EXT=".exe"
+# If we are debugging, add "-g -O0" to the C/C++ flags
+if [ -n "$CHARMDEBUG" ]; then
+    OPTS_CPP="$OPTS_CPP -O0 -g"
 fi
 
-CHARMLIB="$CHARMBIN/../lib"
-CHARMINC="$CHARMBIN/../include"
-CHARMLIBSO=
-if test -d "$CHARMBIN/../lib_so" 
-then
-  CHARMLIBSO=`cd $CHARMBIN/../lib_so 2>/dev/null && pwd`
-  #getting absolute path is harder than thought because of symbolic links and ..
-  #ksh needs cd -P to resolve werid symbolic links, however -P is not portable
-  #csh is ok too if it exists 
-  test -z "$CHARMLIBSO" && CHARMLIBSO=`cd -P $CHARMBIN/../lib_so 2>/dev/null && pwd`
-  test -z "$CHARMLIBSO" && CHARMLIBSO=`csh -c "cd $CHARMBIN/../lib_so >& /dev/null && pwd"`
-  test -z "$CHARMLIBSO" && echo "$CHARMBIN/../lib_so: not found" && exit 1
-fi
-
-
-
 ##############################################################################
 #
 # Load module dependencies.
@@ -714,7 +738,11 @@ findModuleDep() {
 # HACK: add modules to both ends of library list, to avoid
 #  undefined symbol CkRegisterMainModule when it's in a module file.
        POST_LIBRARIES=`AddList $POST_LIBRARIES -lmodule$M`
-       
+       if [ "$M" = "PythonCCS" ]
+            then
+            LINK_PYTHON=1
+        fi
+
        dep=""
 # fixme: should search everything in the -L library paths:
        for dir in `echo . $CHARMLIB`
@@ -764,6 +792,9 @@ Debug "Read config script, setting defaults..."
 
 Debug "Setting vars..."
 
+# Now that we have read the config file, if python is requested, add the correct version
+POST_LIBRARIES=`AddList $POST_LIBRARIES -lpython${CMK_BUILD_PYTHON}`
+
 if [ "$BUILD_SHARE" = "1" ]
 then
        if [ -n "$CMK_NO_BUILD_SHARED" -o -z "$CHARMLIBSO" ]
index f6d07c7ccba685860cbb4f8223b2ca67d0cf3cb0..b5b3a8ca999a1a588c103e91eaa68600b9898148 100644 (file)
@@ -807,11 +807,12 @@ fi
 fi
 
 #### test if Python headers are installed ####
+PYTHON_VERSION=`python -V 2>&1 | awk {'print $2'} | awk -F. {'print $1"."$2'}`
 cat > $t <<EOT
-#include "python/Python.h"
-#include "python/compile.h"
-#include "python/eval.h"
-#include "python/node.h"
+#include "python${PYTHON_VERSION}/Python.h"
+#include "python${PYTHON_VERSION}/compile.h"
+#include "python${PYTHON_VERSION}/eval.h"
+#include "python${PYTHON_VERSION}/node.h"
 
 int main() {
     Py_Initialize();
@@ -820,9 +821,9 @@ int main() {
     PyCodeObject *program = PyNode_Compile(programNode, "");
 }
 EOT
-PYTHON_VERSION=`python -V 2>&1 | awk {'print $2'} | awk -F. {'print $1"."$2'}`
 test_link "whether Python is installed" "yes" "no" "-lpython$PYTHON_VERSION -lpthread -lutil -ldl"
 AC_DEFINE_UNQUOTED(CMK_HAS_PYTHON, $pass, [whether Python is installed])
+AC_DEFINE_UNQUOTED(CMK_PYTHON_VERSION, ${PYTHON_VERSION}, [Python version])
 if test $pass -eq 1
 then
        add_flag "CMK_BUILD_PYTHON=$PYTHON_VERSION" "python"
index fda51cc80583efaa47318086892f1f8f621a212b..616b69410c701228f0b4fd06783798c857f56bcd 100644 (file)
@@ -80,6 +80,8 @@
 
 /* whether Python is installed */
 #undef CMK_HAS_PYTHON
+/* Python version */
+#undef CMK_PYTHON_VERSION
 
 /* whether the sched_setaffinity() exists */
 #undef CMK_HAS_SETAFFINITY
index 354d1091ab4b1d3b1e3ac48ac069a998662b5d46..32e3707c62caa194feedd88958ed3b6bfbed49c5 100644 (file)
@@ -547,9 +547,11 @@ void Chare::sharedDisambiguation(XStr &str,const XStr &super)
     str<<"    }\n";
     if (isPython()) {
       str<<"    void registerPython(char *str) {\n";
-      str<<"      CcsRegisterHandler(str, CkCallback("<<Prefix::Index<<type<<"::pyRequest(0), ";
-      if (isArray()) str<<"ckGetArrayID()";
-      else str<<"ckGetChareID()";
+      str<<"      CcsRegisterHandler(str, CkCallback("<<Prefix::Index<<type<<"::pyRequest(0), ";//<<Prefix::Proxy<<type<<"(";
+      //if (isArray()) str<<"ckGetArrayID()";
+      //else if (isGroup()) str <<"ckGetGroupID()";
+      //else str<<"ckGetChareID()";
+      str << "*this";
       str<<"));\n";
       str<<"    }\n";
     }
@@ -606,6 +608,7 @@ Chare::genRegisterMethodDef(XStr& str)
   str <<  tspec() <<
   "void "<<indexName()<<"::__register(const char *s, size_t size) {\n"
   "  __idx = CkRegisterChare(s, size);\n";
+  if (internalMode) str << "  CkRegisterChareInCharm(__idx);\n";
   // register all bases
   genIndexNames(str, "  CkRegisterBase(__idx, ",NULL, "::__idx);\n", "");
   genSubRegisterMethodDef(str);
@@ -2770,17 +2773,19 @@ void Entry::genPythonDefs(XStr& str) {
   if (isPython()) {
 
     str << "PyObject *_Python_"<<container->baseName()<<"_"<<name<<"(PyObject *self, PyObject *arg) {\n";
-    str << "  int pyNumber = PyInt_AsLong(PyDict_GetItemString(PyModule_GetDict(PyImport_AddModule(\"__main__\")),\"__charmNumber__\"));\n";
-    str << "  CmiLock(CsvAccess(pyLock));\n";
-    str << "  "<<container->baseName()<<" *pyWorker = ("<<container->baseName()<<" *)((*CsvAccess(pyWorkers))[pyNumber]).object;\n";
-    str << "  ((*CsvAccess(pyWorkers))[pyNumber]).arg=arg;\n";
-    str << "  ((*CsvAccess(pyWorkers))[pyNumber]).result=&CtvAccess(pythonReturnValue);\n";
-    str << "  ((*CsvAccess(pyWorkers))[pyNumber]).pythread=PyThreadState_Get();\n";
-    str << "  CmiUnlock(CsvAccess(pyLock));\n";
+    str << "  PyObject *dict = PyModule_GetDict(PyImport_AddModule(\"__main__\"));\n";
+    str << "  int pyNumber = PyInt_AsLong(PyDict_GetItemString(dict,\"__charmNumber__\"));\n";
+    str << "  PythonObject *pythonObj = (PythonObject *)PyLong_AsVoidPtr(PyDict_GetItemString(dict,\"__charmObject__\"));\n";
+    str << "  "<<container->baseName()<<" *object = static_cast<"<<container->baseName()<<" *>(pythonObj);\n";
+    str << "  object->pyWorkers[pyNumber].arg=arg;\n";
+    str << "  object->pyWorkers[pyNumber].result=&CtvAccess(pythonReturnValue);\n";
+    str << "  object->pyWorkers[pyNumber].pythread=PyThreadState_Get();\n";
+    str << "  CtvAccess(pythonReturnValue) = 0;\n";
 
-    str << "  pyWorker->thisProxy."<<name<<"(pyNumber);\n";
+    str << "  //pyWorker->thisProxy."<<name<<"(pyNumber);\n";
+    str << "  object->"<<name<<"(pyNumber);\n";
 
-    str << "  CthSuspend();\n";
+    str << "  //CthSuspend();\n";
 
     str << "  if (CtvAccess(pythonReturnValue)) {\n";
     str << "    return CtvAccess(pythonReturnValue);\n";
@@ -3053,6 +3058,7 @@ void Entry::genCall(XStr& str, const XStr &preCall)
   else { //Normal case: call regular method
     if (isArgcArgv) str<<"  CkArgMsg *m=(CkArgMsg *)impl_msg;\n"; //Hack!
   
+    str << "#ifndef CMK_OPTIMIZE\n  setMemoryChareID(impl_obj);\n#endif\n";
     if(isConstructor()) {//Constructor: call "new (obj) foo(parameters)"
        str << "  new (impl_obj) "<<container->baseName();
     } else {//Regular entry method: call "obj->bar(parameters)"
@@ -3068,6 +3074,7 @@ void Entry::genCall(XStr& str, const XStr &preCall)
     else {//Normal case: unmarshall parameters (or just pass message)
         str<<"("; param->unmarshall(str); str<<");\n";
     }
+    str << "#ifndef CMK_OPTIMIZE\n  setMemoryChareID(NULL);\n#endif\n";
   }
 }