Hatena::ブログ(Diary)

hogeなlog

プロフィール

hogelog

hogelog

小室 直(こむろ すなお)。電気通信大学2003年入学。2010年修士卒業。プログラミングとかしてます。

カレンダー
1984 | 01 |
2006 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 |
2010 | 01 | 06 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 05 | 08 | 09 | 10 | 12 |
2012 | 01 | 04 | 06 |

December 11(Sat), 2010

[][] Lua処理系コード読み(11) global_State

Lua VM一個にglobal_Stateが一個。VMが保持しておくべきアロケータへのポインタとかGCの状態とかを保持しておく。全てのlua_Stateはこのglobal_Stateへの参照を保持する。

/*
** `global state', shared by all threads of this state
*/
typedef struct global_State {
  stringtable strt;  /* hash table for strings */
  lua_Alloc frealloc;  /* function to reallocate memory */
  void *ud;         /* auxiliary data to `frealloc' */
  lu_byte currentwhite;
  lu_byte gcstate;  /* state of garbage collector */
  int sweepstrgc;  /* position of sweep in `strt' */
  GCObject *rootgc;  /* list of all collectable objects */
  GCObject **sweepgc;  /* position of sweep in `rootgc' */
  GCObject *gray;  /* list of gray objects */
  GCObject *grayagain;  /* list of objects to be traversed atomically */
  GCObject *weak;  /* list of weak tables (to be cleared) */
  GCObject *tmudata;  /* last element of list of userdata to be GC */
  Mbuffer buff;  /* temporary buffer for string concatentation */
  lu_mem GCthreshold;
  lu_mem totalbytes;  /* number of bytes currently allocated */
  lu_mem estimate;  /* an estimate of number of bytes actually in use */
  lu_mem gcdept;  /* how much GC is `behind schedule' */
  int gcpause;  /* size of pause between successive GCs */
  int gcstepmul;  /* GC `granularity' */
  lua_CFunction panic;  /* to be called in unprotected errors */
  TValue l_registry;
  struct lua_State *mainthread;
  UpVal uvhead;  /* head of double-linked list of all open upvalues */
  struct Table *mt[NUM_TAGS];  /* metatables for basic types */
  TString *tmname[TM_N];  /* array with tag-method names */
} global_State;

[][] Lua処理系コード読み(12) lua_newstate

lua_newstateは一個のlua_Stateとglobal_Stateからなるメインスレッド(ネイティブスレッドではなくいわゆるグリーンスレッド)を初期化する関数。基本的には領域とってきて値を設定してるだけです。

LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
  int i;
  lua_State *L;
  global_State *g;
  void *l = (*f)(ud, NULL, 0, state_size(LG));
  if (l == NULL) return NULL;
  L = tostate(l);
  g = &((LG *)L)->g;
  L->next = NULL;
  L->tt = LUA_TTHREAD;
  g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);
  L->marked = luaC_white(g);
  set2bits(L->marked, FIXEDBIT, SFIXEDBIT);
  preinit_state(L, g);
  g->frealloc = f;
  g->ud = ud;
  g->mainthread = L;
  g->uvhead.u.l.prev = &g->uvhead;
  g->uvhead.u.l.next = &g->uvhead;
  g->GCthreshold = 0;  /* mark it as unfinished state */
  g->strt.size = 0;
  g->strt.nuse = 0;
  g->strt.hash = NULL;
  setnilvalue(registry(L));
  luaZ_initbuffer(L, &g->buff);
  g->panic = NULL;
  g->gcstate = GCSpause;
  g->rootgc = obj2gco(L);
  g->sweepstrgc = 0;
  g->sweepgc = &g->rootgc;
  g->gray = NULL;
  g->grayagain = NULL;
  g->weak = NULL;
  g->tmudata = NULL;
  g->totalbytes = sizeof(LG);
  g->gcpause = LUAI_GCPAUSE;
  g->gcstepmul = LUAI_GCMUL;
  g->gcdept = 0;
  for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL;
  if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
    /* memory allocation error: free partial state */
    close_state(L);
    L = NULL;
  }
  else
    luai_userstateopen(L);
  return L;
}

メモリロケーション命令のエラーが発生しかねない初期化に関してはf_luaopen関数の中にまとめてluaD_rawrununprotected関数経由で呼ぶ。luaD_rawrununprotected内部にはtry/catch(のようなもの)があり、f_luaopen内部からthrowが飛んでくるとエラーを返す。f_luaopenが正常に実行できていれば0を返す。つまり

  else
    luai_userstateopen(L);

はf_luaopenがエラー(メモリが足りないとかアロケータが腐ってるとかそういう状況。つまり普通エラーにならない)じゃなければ呼ばれる。

LG, LUAI_EXTRASPACE, state_size(LG), tostate(l), fromstate(l)

typedef struct LG {
  lua_State l;
  global_State g;
} LG;

LGはまあ見たまんまの。

/*
@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State
@* (the data goes just *before* the lua_State pointer).
** CHANGE (define) this if you really need that. This value must be
** a multiple of the maximum alignment required for your machine.
*/
#define LUAI_EXTRASPACE		0

#define state_size(x)	(sizeof(x) + LUAI_EXTRASPACE)
#define fromstate(l)	(cast(lu_byte *, (l)) - LUAI_EXTRASPACE)
#define tostate(l)   (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE))

state_size(LG)=state_size(L)+sizeof(global_State)=sizeof(L)+LUAI_EXTRASPACE+sizeof(global_State)。スレッド領域を確保するときにLUAI_EXTRASPACE分も確保してくれて、fromstate(L)とかすることでその領域のアドレスを得ることができる。スレッド毎に保持しておきたいデータがあればここをいじる。LuaさんはCアプリに組み込んで使うことが多いのでこういうことができるように。

/*
@@ luai_userstate* allow user-specific actions on threads.
** CHANGE them if you defined LUAI_EXTRASPACE and need to do something
** extra when a thread is created/deleted/resumed/yielded.
*/
#define luai_userstateopen(L)		((void)L)
#define luai_userstateclose(L)		((void)L)
#define luai_userstatethread(L,L1)	((void)L)
#define luai_userstatefree(L)		((void)L)
#define luai_userstateresume(L,n)	((void)L)
#define luai_userstateyield(L,n)	((void)L)

メインスレッド初期化のときにluai_userstateopen、他のスレッド初期化時にluastatethreadなど適宣呼んでくれるので初期化したい構造のときはこの名前でdefineしてくださいねということ。luaconf.hを参考に。

[][] Lua処理系コード読み(13) luaL_newstate

luaL_newstateは先のlua_newstateにLuaが提供するシンプルなアロケータ(とエラー発生時呼び出す関数)を指定して呼び出す関数。

LUALIB_API lua_State *luaL_newstate (void) {
  lua_State *L = lua_newstate(l_alloc, NULL);
  if (L) lua_atpanic(L, &panic);
  return L;
}

l_allocの中身はだいぶ謎。nsizeが0のときreallocはfreeと等価なはずだし意味がないのではと思うけど、なんかそうなってない環境があるのかなー。

static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
  (void)ud;
  (void)osize;
  if (nsize == 0) {
    free(ptr);
    return NULL;
  }
  else
    return realloc(ptr, nsize);
}

ud, osizeという引数はこの関数ではもちろん必要ないけど、自作アロケータを使うときに使う。udにそのアロケータが関連付けてないといけない領域が与えられるのでそんな感じに扱いましょう的なそんな。(void)ud;(void)osize;はたぶん警告とかエラーを潰す何かかなー。たいていの環境だと意味はそんなない気がする。

LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) {
  lua_Alloc f;
  lua_lock(L);
  if (ud) *ud = G(L)->ud;
  f = G(L)->frealloc;
  lua_unlock(L);
  return f;
}


LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {
  lua_lock(L);
  G(L)->ud = ud;
  G(L)->frealloc = f;
  lua_unlock(L);
}

lua_getallocf, lua_setallocf経由でアロケータをセットしたり。

December 01(Wed), 2010

[][] OpenCV tracに投げたPythonバインディングAPI cv.KMeans2の修正パッチが取り込まれた。

no title

で投げたOpenCV Pythonバインディングのcv.KMeans2の修正パッチが取り込まれました。

no title

パッチが割とそのまま取り込まれてるのでけっこう嬉しい。以前 OpenCVは「Pythonバインディングを公式サポートしてます!」と言ってるけどイマイチちゃんと動いてなかった。 - hogeなlogで投げたパッチはパッチというか「こういう原因で動かないんですけど」と説明するレベルのいい加減なパッチだったので。

トラックバック - http://d.hatena.ne.jp/hogelog/20101201
最近のコメント