/*  -
   Copyright (C) 2006 Weongyo Jeong (weongyo@gmail.com)

This file is part of ROVM.

ROVM is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.

ROVM is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.  */

#ifndef _ROVM_TICKET_H
#define _ROVM_TICKET_H

#include "core.h"
#include "class.h"

/**
   기본적으로 생성할 스택 slot 의 갯수.
 */
#define DEFAULT_STACK_SLOT              256

#define TICKET_POOL(NODE)               ((NODE)->p)
#define TICKET_MUTEX(NODE)              ((NODE)->mutex)
#define TICKET_TIME(NODE)		((NODE)->tmade)

#define TICKET_SP(NODE)                 ((NODE)->sp)
#define TICKET_MAX_SP(NODE)             ((NODE)->maxsp)
#define TICKET_MIN_SP(NODE)             ((NODE)->minsp)
#define TICKET_LOCAL(NODE)              ((NODE)->local)
#define TICKET_MAXLOCAL(NODE)           ((NODE)->maxlocal)
#define TICKET_RET(NODE)                (&((NODE)->ret))

#define TICKET_STACK(NODE)              ((NODE)->stack)
#define TICKET_STACK_IDX(NODE, IDX)     ((NODE)->stack[(IDX)])
#define TICKET_MAX_STACK_SLOT(NODE)     ((NODE)->max_stack_slot)

/**
   사용자의 request 가 온 후, 생성되는 구조체로써, 사용자가 보낸 여러 정보들의
   상태등을 담고 있으며, 이를 이용하여 다음 요청이 왔을 때에도 계속 사용할 수
   있도록 한다.

   이 구조체는 대단히 중요한 구조체로써 각 request 에 대한 현재 모든 상태들을
   가지고 있다.
 */
struct ticket
{
  /** Ticket 을 위한 메모리 pool.  */
  rc_pool_t *p;

  /**
     Ticket 을 위한 mutex.  이것은 GC thread 와 VM 에서의 작동 방식과의 아주
     작은 오차를 교정하기 위해 사용되는 mutex 이다.  자세히 설명하면 아래와 같다.
     
     현재 GC thread 의 경우, Ticket Tree 를 walking 하면서 이루어지게 되는데,
     아래와 같은 예외 상황이 발생할 수 있습니다.

       * gc_alloc () 함수가 성공적으로 할당된 그 순간 GC 가 이루어질 경우,
         (이 경우, multi thread 이기 때문에 충분히 발생할 수 있습니다.)
         아직 할당된 메모리가 Stack Slot 에 올라가 있지 않을 수도 있습니다.
         이로 인해서 할당된 메모리가 그대로 GC 처리되는 불상사가 발생할 수
         있습니다.

     위에서 발생할 수 있는 예외 상황을 막기 위한 mutex 입니다.  해결 방법론은
     현재 다음과 같습니다.

       1. 모든 Ticket 구조체는 mutex 를 가지도록 설정합니다.
       2. 그리고 gc_alloc () 함수가 실행될 수 있는 opcode 들에 한하여 locking
          메커니즘을 적용합니다.
       3. GC 가 이루어질 때 Ticket 구조체의 locking 메커니즘을 또한 서로
          적용합니다.
  */
  rc_thread_mutex_t *mutex;

  /**
     Ticket 이 생성된 시각을 가지고 있다.  이것은 나중에 일정 시간이 경과한
     ticket 의 경우, 자동 소멸을 위해서 사용된다.
  */
  rc_time_t tmade;

  /** Stack Pointer.  x86 에서 stack pointer 개념이랑 같습니다.  */
  rovm_stack_t *sp;
  /** Stack Pointer 가 최대/최소로 증가하였을 경우의 포인터이다.  이것은 Stack 경계점을
      넘어가는 것을 검사하기 위한 루틴이다.  */
  rovm_stack_t *maxsp;
  rovm_stack_t *minsp;

  /** Local Variable Pointer.  이것은 자바 가상 머신에서의 개념과 거의 같으며
      아래 변수 `stack' 배열중 하나의 slot 을 가르키게 된다.  이에 대한 자세한
      개념은 `Stack 과 Local 변수의 이해' 글을 참고하기 바란다.

      @note 현재 `Stack 과 Local 변수의 이해' 글은 존재하지 않는다.  */
  rovm_stack_t *local;
  /** Local 변수의 최대 slot 에 대한 포인터 정보를 가지고 있으며, iload 와 같은
      opcode 가 잘못된 local 변수 범위 외의 영역에 침범하는지를 판단하는데,
      사용된다.  */
  rovm_stack_t *maxlocal;

  /** Ticket 이 관리하는 스택 slot 들.  스택 배열입니다. */
  rovm_stack_t *stack;
  /** 위 변수 `stack' 에 할당된 스택 slot 의 갯수.  */
  int max_stack_slot;

  /** 현재 ticket operation 이 처리되면서 반환하게 되는 return 값이 설정되는
      위치.  */
  rovm_stack_t ret;
};

extern char *create_ticketid (request_rec *);
extern int gen_unique_ticketid (char *);
extern int register_ticketid (request_rec *, char *);
extern struct ticket *lookup_ticket (request_rec *, char *);
extern int ticket_pre_config ( struct ticket *);
extern int ticket_beforecall (struct ticket *, RvMethod *, u2, u2 *);
extern void destroy_ticket (struct ticket *);
extern int destroy_tickets (request_rec *, char *);

#endif
