일단, 인터럽트라는거 자체가 transient 한지, persistent(맞나?) 한지 부터 생각을 해봐야할거야
나는 컴퓨터의 모든 개념은 persistent 하다고 생각해.
1클럭만 임펄스를 주고 사라진다???? 이렇게 위험한게 어디있음??
아마 그런 의미에서 stream 과 데이터 전송의 실패 (나 지금 네트워크쪽 캐치업하려면 큰일났어)
가 네트워크 아랫 레이어들의 주된 고민이겠지.
여하튼, 컴퓨터의 모든 신호는 persistent 해.
일시적이어 보이는 개념은 회로에 흐르는 전류이지만,
그것또한 클럭을 막아두고, write를 막아둠으로써
"어 나 stalling 안풀면 너가 dependent한 모든 조상들은 움직이지 않아서 너 조차도 변하지 않을거다"
이런식으로 stalling을 진행하니까 ㅇㅇㅇㅇㅇ.
즉,
내 예상은 이래.
IO device가 인터럽트와 함께 인터럽트에 대한 정보까지 system bus로 전달해. 이거는 CS:app 피셜인데, 뭐 대충 그렇다고 하자.
아니 그러면 수많은 IO 인터럽트들이있을텐데, 그걸 어떻게 CPU가 받아들여요?
컨커런씨는 어떡하고요???
그냥 이렇게 하자.
어차피 운영체제가 1클럭당, 아니 애초에 하나의 인터럽트 처리가 1클럭만에 파이프라인화가 되지 않을거라고 보는게 타당하니,
단위클럭당 하나의 인터럽트만 처리가 가능할거임.
그 때 처리한다 = stalling을 해제한다 = 막아두었던 담을 해제하고 정보를 받는다.
가 되는거고,
나머지 모든 인터럽트들은 queue를 이룬다고하자.
이러면
인터럽트들이 수도없이 쌓여서 queue가 넘치면 어떡하나요???
이런것도 죄다 파이프라인의 특정단계에서부터 용량초과문제가 생기기 시작하면 stalling이 일어난다고 생각하자.
클럭으로 제한되는 하드웨어는 생각보다 동시성 이슈에서 자유로울 수 도 있는데,
클럭 이라는 시스템이 있기 때문이야.
나는 인터럽트 단계까지는 클럭시스템이 정상적으로 작동한다고 생각해.
모든 경우의 수를 다 분기해서 클럭에 따른 stalling을 통해 완벽한 제어가 이루어질거야.
그리고 그것의 반례가, 데이터가 조오오온나 물밀듯이 들어오는 UDP일거고, UDP에 대해서는 나중에 알아볼게 라고 하지만 이제 데이터통신 공부 안하면 F뜨게 생겼어서 아마 이번달안으로는 네트워크도 봐야돼.
여하튼 본론으로 돌아오자
그러면 그 클럭이라는 효과적인 시스템이 어째서 고수준까지는 올라오지 못하고 수많은 concurrency 프라블럼을 야기했느냐.
여기에는 나는 세가지 이슈가 있다고 생각해.
1. 몇클럭이 걸릴지 계산하는것은 추상화레이어 및 모듈화에서는 블랙박스이다.
즉, 하드웨어 레이어들은 자기들만의 분기들을 통해서 클럭단위 완전한 제어가 이루어지더라도,
우리는 그것을 원자단위로 계산할 수 없다.
몇 클럭이 걸릴지 예상이 불가능하다는 점에서 기존의 클럭단위는 사라지고,
인간 수준의 시계에서 클럭단위는 매우 미세하기에, 마치 연속적으로 (어 그 중간에 뭐가 껴들어가면? 어 그거랑 그거랑 겹쳐서 즉 동시에 일어나면?)
이런식으로,
사실 추상화레이어를 조금만 올라와서 원자단위의 계산을 안하고 모듈화를 시작하면
거기서부터는 더이상 아토믹한 클럭단위의 시스템이 아니다.
사실상 연속된 시간개념으로 추상화레이어가 전환된다.
2. 캐쉬 문제.
캐쉬는 완전한 제어가 불가능하다. 그러니까 이거를 죄다 명시해주면 제어가 가능한데, 그것은 원자적 단위인 셈이다. 이 캐쉬문제와 관련된게 동기화에서 핵심된 내용이고, 캐쉬가 조온나 골치아픈건 사실이다.
3. ILP 문제.
ILP 또한 인간의 추상화 수준과 하드웨어의 실제 클럭단위 작용이 달라지는 요인이다.
4. 원자적 단위의 충돌.
이건 뭐 별건 아니다. 단지 규약이 어떤지만 알고가야하는건데, 특정 register 가 read/write 가 동시에 일어날 경우? 와 같은 원자적단위의 하드웨어문제에서 기인한다.
이거 같은 경우는 그냥, write로 들어오는 데이터가 그대로 read 로 나간다 뭐 이런식으로 간단하게 해결되는 문제이지만, 생각할 거리를 한단계 더 늘려주긴 한다.
난 이 네가지로 보고있음.
그리고, 인터럽트는 해당 네가지에 해당되지 않고,
따라서
stalling 이라던지 파이프라인이라던지,
내부의 대기 queue 를 통해서 저수준 제어가 완벽하게 이뤄질거라고 생각한다.
또한, 인터럽트에 데이터가 보내지지 않고 상태비트만 보내진다고 오해를 했어서,
인터럽트를 보내는 주체가 직접 커널의 메모리에 손을 댄다는식으로 추정을 했었다. 그리고 그 말은 즉, 굉장한 concurrency 프라블럼을 야기한다.
이것 또한, 인터럽트와 함께 시스템 버스에 인터럽트에 대한 정보를 보내며,
해당 stalling 과 enque dequeue 가 정확히 다루어진다는 가정하에는 다시 문제가 생기지 않는다.
그렇다면, 이제 마지막으로
" I/ O 인터럽트에 대한 핸들러는 정확히 무슨일을 하고, 아마 커널영역에서 움직이면서 프로세스들의 스케쥴링 전략에까지 영향을 미칠텐데, 그 상호작용의 정확한 디테일은 무엇입니까?" 만이 의문인데
이거는 뭐 언젠간 흘러들어오는 소식에 의해서 아 그런식이구나~ (뭐 공룡책에 나온다던지) 하는 식으로 넘기면 될거같고,
그냥 일단은 저 부분은 구현을 받아들이면 될 거같다.
저런 구현 하나하나 다 이해하려다간 진짜로
컴퓨터 해부학적으로 완벽해지고, 노가다만 남 시키면 컴퓨터와 운영체제를 만들 수 있게 되는건데...
뭐 교수님중 한분은 대학원급 인력 3명만 있으면 운영체제 만들 수 있다고 하니까 사실 뭐 진짜로 컴퓨터 해부학을 전부 뜯어보는것도 불가능하진 않을거 같기도 함.
근데 난 일단 딱 여기까지. ㅇㅇㅇㅇㅇ
I/o인터럽트에 대한 핸들러에 대한거 직전에서 딱 끝내면 될거같다.
아 그리고 2번 3번과 관련해서 메모리 배리어, 메모리 오더링, 캐쉬 코히어런스 등의 고급개념이 등장한다고 생각한다. 일단, 멀티프로세서 동기화 수업에서 다루는 각종 unsafe 를 safe로 바꿔나가는 방법. 난 이건 잘 모르겠다. 이 거에 대해 모르겠는 이유는, 클락을 통해서 모든것을 만드는데, 오히려 클락이라는 safe 한 시스템을 통해서 unsafe 를 만들어나가는 중이라고 보이고, 따라서 내가 해야할거는 어디에서 unsafe해진건지를 발견해서 해당 추상화에 명시적인 제한을 두는것이지
safe 가 고수준을 위해 unsafe 해졌고, 그 unsafe를 다시 unsafe들을 어떤 알고리즘적인 기막힘으로 safe를 구현해볼것인가. 이거는 내 관점에서는 컴퓨터공학적으로는 굉장히 언짢다. 컴퓨터싸이언스적으로는 하드웨어에 의존하지 않고 추상화 레이어를 통해, unsafe여도 safe로 바까서 쓰는 방법에 대해 생각하는게 중요하다고 생각하고, 나는 해당 지식이 하드웨어쪽으로 흘러들어가면 하드웨어의 발전이 이루어질거라고 생각한다. 클락 이외의 동기화기법을 추가할 수 있는거니까. 아니 애초에 이미 클락 이외의 동기화기법이 존나 많이들어갔을거같다.
여하튼, 나는 하드웨어를 명시적으로 활용하고 싶다. concurrency 안정성을 구현하는 첫번째 방법은, 하드웨어를 명시적으로 사용할 수 있고, 어떤 작업들이 위험한것인지를 인지하는거라고 생각한다. 어차피 맨 아랫단계로 내려가면 클락이 있기 때문이다. 맨 아랫 레이어가 자연현상, 임펄스들과 이벤트들의 연속이었으면 당연히 이러한 접근은 불가능하다.
그냥 죄다 stalling 으로 생각하자고 마음먹었지만, 내부적으로는 cs 적인 천재적인 기법들로 stalling 에 따른 클럭낭비를 최소화시켰다고 생각한다. ㅇㅇㅇ 그러니까 내가 막 unsafe -> safe 가 아니라 safe -> unsafe 다 라는 관점은, (즉 필요에 따라서 safe -> unsafe 자동화를 진행하지 않고 safe -> safe로 명시하라는 관점은) 프로그래머 입장인 나의 관점인거고, unsafe -> safe 를 만드는 과정이 불필요하다는 생각은 아니다 ㅇㅇㅇㅇ
stalling 이 결국 lock 을건다던지 wait을 하는건데, cs적인 기법을 살펴보면 wait-free lock-free가 너무 많아서 ㅇㅇㅇ 근데 나는 은근히 저쪽에 재능도 없고 ㅇㅇㅇㅇㅇㅇ 난 은근히 창의력이 높지 않음. 맥락에 적응하고 거기에 헤엄치는걸 잘하는데, 이걸 잘한다는거 자체가 내 입장에선 창의성이 아니야. 그냥 전형적이고 또 전형적인데, 너무 전형적이다보니까 남들이 보기엔 좀 달라보여서 그걸 창의성이라고 표현하더라고?? 난 창의성 없어
인터럽트는 현재 실행중인 컨텍스트에게 전달된다. 이때, 인터럽트는 인터럽트 정보와 함께 데이터들이 stall 된다 (인터럽트 본인도 당연히 stall). 즉, 해당 stall 된 데이터 속에, 해당 인터럽트가 누구를 위한 것인지가 써져있고. 우리가 소프트웨어적으로 인터럽트를 A에게 보냈다라고 하는것은 보통 해당 인터럽트 정보 속에 담겨있는 목적지 데이터일것이다. 하드웨어적으로 인터럽트는 코어가 현재 실행중인 컨텍스트에게 전달될것이다