공학용 계산기 TI-NSpire CX Emulator, Firebird

계산기 2023. 3. 29. 00:07 posted by tolkien

( https://m.blog.naver.com/nicecan/221112291936 ,

  https://cafe.naver.com/calc/33845 를 많이 참고했습니다.)

TI-NSpire 공식 에뮬레이터 대신 open source로 공개되어 있는 Firebird Emulator를 사용하는 방법입니다.

 

준비하기

1. BootCode를 아래 site에 가서 download 받습니다. (제일 아래로 내려가서 Boot1cx.img, Boot2cx.img만 받으시면 됩니다.)

https://www.intereseducation.com/resources/how-to-emulate-ti-nspire-cx-cas-touchpad-on-mac-windows-linux-with-firebird/

2. TI-Spire CX CAS ROM file은 TI 공식 홈페이지에서 받습니다.
- TI-Nspire™ CX CAS Handheld Operating System - Texas Instruments - US and Canada

3. 그리고, Firebird Emulator 실행파일은 

- Releases · nspire-emus/firebird (github.com) 에 가서 firebird-emu-win64.zip을 download.

파일을 한데 모아놓고, (예를 들어, E:\Users\john\Documents\calc-TI\Emu) 아래와 같이 설정합니다.

 

설치 및 설정하기

4. firebird-emu-win64.zip을 풀고나면, directory에 있는 firebird-emu.exe를 실행하면 아래와 같이 설정화면이 뜹니다. (그림 1)

5. 이제 파일들을 하나하나 지정해주어야 합니다.

  A. Boot1 : Boot1cx.img

  B. Flash에서는 "+" Icon을 눌러서 Flash File을 생성하는 화면(그림 2)으로 가서

      Boot2 : Boot2cx.img, OS : TI에서 받는 OS image (여기서는 TI-NspireCXCAS-4.3.0.702.tcc) 지정해주고, Save button을 누르면 FlashFile 이름을 물어보는데, 적당한 이름을 넣어줍니다. (저는 Firebird-flash.bin 이라고 주었습니다.)

 C. Snapshot button을 누르면 파일이름을 물어보는데, 적당한 이름을 넣어줍니다. (저는 Firebird-snapshot.raw 라고 주었습니다.) 제대로 설정이 되면 그림 3처럼 됩니다.

6. 그리고,  OK button을 누르면 Firebird Emu의 Desktop UI가 나옵니다. 모바일 UI가 실제 기기와 비슷해서 그걸로 설정합시다. Tools -> Switch To Mobile UI를 선택하면 아래와 같은 화면이 나옵니다. (그림 4, 크기를 적당히 조절해서 화면이 다 나오게 합시다)

7. 여기서 "Swipe here"을 누르면, 설정화면이 나오는데 여기서 "Start"를 누릅니다. (그림 5)

8. 좀 있으면 다음과 같은 화면이 나오는데, 여기서 " i " button을 누릅니다. (그림 6, PC가 아니라 emulator에 있는 " i " button입니다.)

9. 조금 기다리면 Firebird Emu가 TI-NSpire OS를 돌릴 준비가 된 것을 알 수 있습니다. (그림 7)

A futex overview and update

Personal Computer/Linux 2023. 3. 27. 22:38 posted by tolkien

 Rusty Russell, Hubertus Franke, Mathew Kirkwood에 의해 2.5.7에 도입된 futex 메커니즘은 사용자 애플리케이션을 위한 빠르고 가벼운 kernel-assisted locking primitive이다. 이것은 매우 빠른 비경합(uncontended) locking 획득 및 해제를 제공한다. futex 상태는 사용자 공간 변수(모든 플랫폼에서 부호 없는 32비트 정수)에 저장된다. atomic operation은 syscall의 오버헤드 없이 경합하지 않는(uncontended) 경우 futex의 상태를 변경하기 위해 사용된다. 경합(contended)하는 경우 커널을 호출하여 작업을 절전 모드로 전환하고 절전 모드를 해제한다.
 futex는 thread programming에서 일반적으로 사용되는 몇 가지 상호 배제(mutual exclusive) 구조의 기초이다. 여기에는 pthread mutex, condvar, semaphore, rwlock 및 장벽이 포함된다. 그들은 지난 몇 년 동안 많은 재건(reconstructive) 수술과 성형(cosmetic) 수술을 겪었고, 이제 그 어느 때보다 더 효율적이고, 더 기능적이며, 더 잘 문서화되었다.

 

Overview

 futex를 직접 사용하는 애플리케이션 개발자는 거의 없지만, 나중에 제시된 개선 사항을 평가하기 위해서는 그 방법에 대한 대략적인 지식이 필요하다. 간단한 예를 들어, futex는 잠금 상태를 저장하고 잠금에서 작업을 차단하기 위한 커널 대기열(waitqueue)을 제공하는 데 사용될 수 있다. syscall 오버헤드를 최소화하려면 잠금이 중단되지 않은 경우 이 상태에서 원자 잠금(atomic lock)을 획득할 수 있어야 한다. 상태는 다음과 같이 정의할 수 있다:


    0. unlocked
    1. locked

 

 locking을 획득하기 위해 atomic test-and-set 명령(예: cmpxchg())을 사용하여 0을 테스트하고 1로 설정할 수 있다. 이 경우, locking thread는 커널을 포함하지 않고 lock을 획득한다(그리고 커널은 이 futex가 존재한다는 것을 알지 못한다). 다음 스레드가 잠금을 획득하려고 할 때 0에 대한 테스트가 실패하고 커널이 관여해야 한다. 그런 다음 blocked thread는 futex_WAIT opcode와 함께 futex() 시스템 호출을 사용하여 futex에서 자체를 절전 모드로 전환하여 futex 상태 변수의 주소를 인수로 전달할 수 있다. 잠금을 해제하기 위해 소유자는 잠금 상태를 0(잠금 해제)으로 변경하고 FUTEX_WAKE opcode를 실행한다. FUTEX_WAKE opcode는 blocked thread를 사용자 공간으로 돌아가 잠금을 획득하려고 시도한다(위에서 설명한 대로). 이것은 최적화의 여지가 많은 명백한 사소한 예이다. Ulrich Drepper의 "futex are tricky"는 여전히 mutex와 같은 locking primitive를 구축하기 위해 futex를 사용하는 것에 대한 좋은 참조 문서이다. 여기에 제시된 예를 개선하기 위한 최적화뿐만 아니라 futex 사용과 관련된 많은 race condition을 언급하고 있다.
 사용자 thread가 futex() 시스템 호출과 함께 커널에 호출할 때 futex 상태의 주소(uaddr), 수행할 opcode(op) 및 다양한 다른 인수를 전달한다. uaddr은 커널이 futex를 참조하는 고유한 "futex_key"를 생성하는 데 사용된다. thread가 FUTEX_WAIT와 같이 futex에서 차단을 요청할 때, "futex_q"가 생성되고 "futex_queues" 해시 테이블에 queuing된다. futex에서 차단된 모든 작업에 대해 하나의 futex_q가 존재하며, 많은 futex당 futex_q가 존재할 수 있다. 여러 개의 futex_key가 동일한 큐에 해시하기 때문에 futex_queue 자체("futex_q's"가 아닌 해시 테이블 목록)는 futex 간에 공유된다. 이러한 관계는 아래에 설명되어 있다:

 대부분의 경우 사용자 공간 상태 변수를 사용하는 방법을 정의하는 정책은 없다. 응용 프로그램(또는 glibc와 같은 라이브러리)은 이 값을 사용하여 구현되는 locking 구조의 상태를 정의합니다. 이것은 부울 변수만큼 간단할 수 있지만(위의 예에서처럼) 최적화된 구현과 다른 locking 메커니즘은 더 복잡한 상태 값을 필요로 한다.
 커널은 간단한 FUTEX_WAIT 및 FUTEX_WAKE 작업 외에도 잠금 구조의 상태에 대한 지식이 사용자 공간에서 가질 수 있는 것보다 더 많은 지식을 필요로 하는 priority inheritance(PI) 체인과 강력한 목록을 관리한다. PI 및 강력한 futex는 상태 변수와 관련된 사용자 정의 정책 규칙의 예외이다. 그들의 상태는 mutex의 잠긴 상태뿐만 아니라 소유자의 신원과 웨이터의 유무에 따라 달라진다. 이와 같이 futex 값은 소유자의 스레드 식별자(TID)와 보류 중인 소유자를 나타내는 비트로 정의된다. 이 정책을 사용하면 사용자 공간 atomic operation을 통해 중단되지 않은 경우 커널 호출을 피할 수 있다.

 

개선 사항

 futex는 2.5.7에 처음 등장한 이후 소수의 개발자들로부터 수많은 개선을 보았다. 일부 주목할 만한 개선 사항에는 실시간 작업에 대한 우선 순위 기반 wakeup(Pierre Peifer)과 강력한 PI futex(Ingo Molnar 및 Thomas Gleixner)가 포함된다. 이러한 후자의 기능은 한동안 사용되어 왔으며 커널 메일링 목록에 대한 훌륭한 토론뿐만 아니라 LWN.net 에서도 적절하게 다루어졌다. 저자의 futex에 대한 시도는 2년반전 여기서 시작되었다. 희귀한 corner case와 race condition을 해결하기 위한 몇 가지 수정 사항 외에도, futex 코드는 이전의 기여 이후로 몇 가지 기능과 성능 향상을 보았다.
 futex 오버헤드를 줄이기 위해 상당한 노력을 기울였다. Eric Dumaze은 PTHREAD_PROCESS_PRIVATE pthread mutex에 대한 최적화로 private futex를 도입했다. private futex는 동일한 프로세스의 thread에서만 사용할 수 있다. 이들은 단순히 가상 주소로 서로 구별할 수 있는 반면, shared futex는 각 프로세스에서 서로 다른 가상 주소를 가지고 있어 커널이 고유한 식별을 위해 물리적 주소를 검색해야 한다. 이 최적화를 통해 private futex에 mmap_sem semaphore를 사용할 필요가 없으므로 시스템 전체의 경합이 줄어든다. 또한 private futex의 reference counting에 사용되는 atomic operation을 제거하여 SMP 머신에서 cache-line 바운스가 줄어든다. Glibc는 이제 기본적으로 private futex를 사용한다.
 Peter Ziljstra는 빠른 경로에서는 get_user_pages_fast()를 사용하고, (일반적인 상황에서는) get_user_pages()를 사용하며, 느린 경로 주변에서만 mmap_sem lock을 사용하도록 강하게 푸시함으로써 futex의 mmap_sem 의존성을 더욱 줄였다(2008년 9월). 이러한 변경은 kernel/futex.c에서 가상 메모리 관련 로직의 대부분을 제거하여 코드를 상당히 단순화하는 추가적인 이점이 있었다. 사용자 공간 주소에 의존하기 때문에 futex는 몇 가지 가능한 fault point을 부담한다. mmap_sem을 사용하는한, get_user()를 호출하기 전에 해제해야 했기 때문에 장애 로직이 복잡해졌다. mmap_sem 사용이 줄면서 작성자는 장애 로직을 크게 단순화하여(2009년 3월) 훨씬 더 읽기 쉬운 코드를 생성했다.
 bitset conditional wakeup은 glibc에서 최적화된 rwlock 구현을 가능하게 하기 위해 Thomas Gleixner(2008년 2월)에 의해 추가되었다. FUTEX_WAIT_BITSET 및 FUTEX_WAKE_BITSET을 사용하면 대기 시간에 동일한 bitset(또는 FUTEX_BITSET_MATCH_ANY와 같은 수퍼 세트)를 지정한 작업으로 wake up task를 제한하는 bitmask를 지정할 수 있다.
 PI futex의 도입 이후, pthread_cond_broadcast()의 glibc condvar 구현은 PI futex로의 대기열을 위한 지원이 부족하기 때문에 FUTEX_REQUEUE의 이점을 활용하지 않고 모든 대기자를 깨울 수밖에 없었다. 이것은 모든 waiter들이 사용자 공간으로 돌아가 lock을 얻기 위한 다툼을 벌이기 때문에 웨이크업 스톰(wakeup storm)이 발생한다. 또한 우선 순위가 가장 높은 작업이 먼저 잠금을 획득하는지 확인하지 못한다. 최근 커널(2.6.31-rt* 및 2.6.32-rc*)에는 이제 작성자의 FUTEX_CMP_REQUEUE가 추가되었다. PI 패치(2009년 4월)는 비PI futex에서 PI futex로 waiter를 대기시키기 위한 커널측 지원을 제공한다. Dinakar Guniguntala의 작업에서 glibc 패치를 통해 실시간 애플리케이션은 곧 guaranteed wakeup order와 더 적은 overall wake-up으로 pthread conditional variable을 사용할 수 있게 될 것이다.

 

자 이제는 뭐죠?

 현재 구현된 kernel/mutex.c를 뒤로 하고, futex 개발자들은 다음 항목들을 고려하고 있다. (다음 단계에 처리할 항목을 담은 문서가 아직 나와 있지 않다.)

man page: 현재 man 페이지에는 새로운 futex 작업의 일부가 포함되어 있지 않다. 이들은 futex의 값에 대한 정책을 제안하고 있으며, 이로 인해 futex 사용에 대한 혼란이 발생하고 있다. 무엇보다도, 사용자 공간 futex() 정의가 /usr/include/linux/futex.h에서 제거되어 man 페이지가 불완전할 뿐만 아니라 부정확해졌다. futex 사용자는 syscall 인터페이스를 직접 사용해야 한다.

adaptive futex: futex의 스케줄링 오버헤드 중 일부는 커널에서 잠들기 전에 적절한 양의 spinning으로 줄일 수 있다. 그러나, futex가 그들의 상태를 사용자 공간에 노출시키기 때문에, 이 spinning은 현재 glibc의 adaptive mutex에서 수행되는 것처럼 사용자 공간에서도 수행될 수 있으며, 소유자가 실행 중인지 여부에 대한 지식이 없어도 spinning은 단순한 최대 재시도 루프로 감소된다.

interruptible futex: 대규모 독점 소프트웨어 프로젝트의 interrupt blocking lock operation에 관심이 있다. 현재 Futex 작업은 signal 발생 시 -EINTR을 사용자 공간으로 되돌리는 대신 자체적으로 재시작된다. futex는 FUTEX_INTRUSTIBLE로 플래그가 지정될 수 있으며, signal발생으로 인한 wakeup시 이 플래그는 시스템 호출을 다시 시작해야 하는지 또는 -ECANCELED를 사용자 공간으로 반환해야 하는지 결정한다. 이러한 기능을 pthread lock primitive로 공개하면 pthread 라이브러리에 대한 non-POSIX compliant 변경이 수반되지만 이는 전례가 없는 것은 아니다.

scalability enhancement: LKML은 NUMA에 최적화된 해시 테이블뿐만 아니라 비공개 해시 테이블에 대해서도 논의되어 왔다. futex 해시 테이블은 모든 프로세스에서 공유되며 특히 대규모 시스템에서 실제 오버헤드로 이어질 수 있는 spinlock에 의해 보호된다. 이 오버헤드는 시스템이 NUMA 노드에서 파티셔닝되거나 private futex를 단독으로 사용하는 프로세스에 대해서는 적용되지 않는다.

futex test suite: 작성자가 futex 기능을 검증하기 위해 전체 테스트 제품군에 대한 요구 사항 목록을 작성하고 있다. 이 test suite는 향후 개발을 위한 regression suite 역할을 할 것이다. futex로 가능한 많은 corner case와 misuse case는 test suite를 복잡하게 만들고 설계에 문제를 제기한다.

 

Acknowledgement

나는 John Stultz, Will Schmidt, Paul McKenney, Nivedita Singhvi, 그리고 물론 Jon Corbet에게 감사를 표하고 싶다. 그의 리뷰는 이 기사를 그렇지 않았을 때보다 훨씬 더 읽기 쉽고 완전하게 만들었다.

TI-84/TI-83 plus에서 가장 아쉬운 것이 복소수 행렬지원입니다. 정확히 말하면 복소수 행렬을 통한 복소수 연립방정식이죠. 이 기능의 부재로 인해서 같은 회사의 상위기종인 TI-89나 TI-NSpire로 넘어가게 됩니다. 아니면, 카시오 fx-9860 시리즈로 가게 되죠. (fx-9750 시리즈는 지원하지 않습니다. 그외 레어템인 TI-86, 카시오 afx-2.0 등이 복소수 행렬 연산을 지원합니다.)

 그래서, 이에 극복하기 위한 여러 방법이 있는데, 그중에서 아리조나 주립대 공과대학에서 작성한 TI-84/TI-83plus용 app이 사용하기 깔끔하기에 소개합니다. 아래식을 예로 들면,

(1+i)x -2iy = 6-2i
3ix + (-2+i)y = -1
  1. SIMEQMWM.8xp를 설치하고,
  2. STAT -> Edit... -> L1에 입력합니다. 순서는 x계수, y계수, R-value 순으로.
  3. 2nd -> Quit로 종료한 다음에, SIMEQMWM을 실행합니다. NUM=?을 물어보면 미지수 갯수인 2를 입력합니다.
  4. 다시 STAT -> Edit... 로 들어가면 L2에 해가 들어 있습니다. (참,  쉽죠?)

TI-BASIC code이므로 다른 계산기에도 이식이 쉽게 될 것같습니다. (->은 STO, L1, L2는 List 1, List 2입니다.)

SetUpEditor
ClrList L2
Prompt N
{2N,2N+1->dim([A])
For(I,1,N)
For(J,1,N)
real(L1((I-1)N+I+J-1))->[A](I,J)
[A](I,J)->[A](N+I,N+J)
imag(L1((I-1)N+I+J-1))->[A](N+I,J)
-[A](N+I,J)->[A](I,N+J)
End
real(L1(I(N+1)))->[A](I,2N+1)
imag(L1(I(N+1)))->[A](N+I,2N+1)
End
rref([A])->[A]
For(I,1,N)
[A](I,2N+1)+i[A](N+I,2N+1)->L2(I)
End
DelVar [A]

 

참고문헌

  1. https://uweb.engr.arizona.edu/~mwm/classes/220/Other_Resources/SIMEQMWM.htm
  2. https://education.ti.com/en/customer-support/knowledge-base/ti-83-84-plus-family/product-usage/34843
  3. https://m.blog.naver.com/kyhilsang131/221863854577
  4. https://allcalc.org/21582

SIMEQMWM.8xp
0.00MB